ma question est montrée dans ce code
J'ai cours comme ça
public class maincs
{
public int a;
public int b;
public int c;
public int d;
}
public class sub1
{
public int a;
public int b;
public int c;
}
public void methoda (sub1 model)
{
maincs mdata = new maincs(){a = model.a , b = model.b , c= model.c} ;
// is there is a way to directly cast class sub1 into main like that
mdata = (maincs) model;
}
Ce qu'il veut dire, c'est:
"Si vous avez deux classes partageant la plupart des mêmes propriétés, vous pouvez convertir un objet de la classe a
en classe b
et faire en sorte que le système comprenne l'affectation via les noms de propriétés partagées?"
Option 1: utiliser la réflexion
Inconvénient: ça va te ralentir plus que tu ne le penses.
Option 2: Faites en sorte qu'une classe dérive d'une autre, la première ayant des propriétés communes et l'autre une extension de celle-ci.
Inconvénient: couplé! si vous faites cela pour deux couches dans votre application, les deux couches seront couplées!
Qu'il y ait:
class customer
{
public string firstname { get; set; }
public string lastname { get; set; }
public int age { get; set; }
}
class employee
{
public string firstname { get; set; }
public int age { get; set; }
}
Maintenant, voici une extension pour le type d'objet:
public static T Cast<T>(this Object myobj)
{
Type objectType = myobj.GetType();
Type target = typeof(T);
var x = Activator.CreateInstance(target, false);
var z = from source in objectType.GetMembers().ToList()
where source.MemberType == MemberTypes.Property select source ;
var d = from source in target.GetMembers().ToList()
where source.MemberType == MemberTypes.Property select source;
List<MemberInfo> members = d.Where(memberInfo => d.Select(c => c.Name)
.ToList().Contains(memberInfo.Name)).ToList();
PropertyInfo propertyInfo;
object value;
foreach (var memberInfo in members)
{
propertyInfo = typeof(T).GetProperty(memberInfo.Name);
value = myobj.GetType().GetProperty(memberInfo.Name).GetValue(myobj,null);
propertyInfo.SetValue(x,value,null);
}
return (T)x;
}
Maintenant, vous l'utilisez comme ceci:
static void Main(string[] args)
{
var cus = new customer();
cus.firstname = "John";
cus.age = 3;
employee emp = cus.Cast<employee>();
}
La méthode cast vérifie les propriétés communes entre deux objets et effectue l'affectation automatiquement.
Vous avez déjà défini la conversion, il vous suffit de faire un pas de plus si vous souhaitez pouvoir effectuer un casting. Par exemple:
public class sub1
{
public int a;
public int b;
public int c;
public static explicit operator maincs(sub1 obj)
{
maincs output = new maincs() { a = obj.a, b = obj.b, c = obj.c };
return output;
}
}
Ce qui vous permet ensuite de faire quelque chose comme
static void Main()
{
sub1 mySub = new sub1();
maincs myMain = (maincs)mySub;
}
using Newtonsoft.Json;
Class1 obj1 = new Class1();
Class2 obj2 = JsonConvert.DeserializeObject<Class2>(JsonConvert.SerializeObject(obj1));
public class Class1
{
public static explicit operator Class2(Class1 obj)
{
return JsonConvert.DeserializeObject<Class2>(JsonConvert.SerializeObject(obj));
}
}
Ce qui vous permet ensuite de faire quelque chose comme
static void Main()
{
Class1 obj1 = new Class1();
Class2 obj2 = (Class2)obj1;
}
Vous pouvez modifier la structure de votre classe pour:
public class maincs : sub1
{
public int d;
}
public class sub1
{
public int a;
public int b;
public int c;
}
Ensuite, vous pourriez garder une liste de sub1 et en envoyer certains à mainc.
Vous pouvez fournir une surcharge explicite à l'opérateur de conversion:
public static explicit operator maincs(sub1 val)
{
var ret = new maincs() { a = val.a, b = val.b, c = val.c };
return ret;
}
Une autre option consisterait à utiliser une interface possédant les propriétés a, b et c et à implémenter l'interface sur les deux classes. Ensuite, il suffit que le type de paramètre à methoda soit l'interface au lieu de la classe.
En utilisant ce code, vous pouvez copier n'importe quel objet de classe dans un autre objet de classe avec le même nom et le même type de propriétés.
JavaScriptSerializer JsonConvert = new JavaScriptSerializer();
string serializeString = JsonConvert.Serialize(objectEntity);
objectViewModel objVM = JsonConvert.Deserialize<objectViewModel>(serializeString);
En utilisant le code suivant, vous pouvez copier tout objet de classe dans un autre objet de classe pour le même nom et le même type de propriétés.
public class CopyClass
{
/// <summary>
/// Copy an object to destination object, only matching fields will be copied
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="sourceObject">An object with matching fields of the destination object</param>
/// <param name="destObject">Destination object, must already be created</param>
public static void CopyObject<T>(object sourceObject, ref T destObject)
{
// If either the source, or destination is null, return
if (sourceObject == null || destObject == null)
return;
// Get the type of each object
Type sourceType = sourceObject.GetType();
Type targetType = destObject.GetType();
// Loop through the source properties
foreach (PropertyInfo p in sourceType.GetProperties())
{
// Get the matching property in the destination object
PropertyInfo targetObj = targetType.GetProperty(p.Name);
// If there is none, skip
if (targetObj == null)
continue;
// Set the value in the destination
targetObj.SetValue(destObject, p.GetValue(sourceObject, null), null);
}
}
}
Méthode d'appel
ClassA objA = new ClassA();
ClassB objB = new ClassB();
CopyClass.CopyObject(objOfferMast, ref objB);
Il va copier objA
dans objB
.
Il y a quelques bonnes réponses ici, je voulais juste ajouter un peu de vérification de type ici car nous ne pouvons pas supposer que si des propriétés portent le même nom, elles sont du même type. Voici mon offre, qui s'étend sur la précédente, très excellente réponse car j'avais quelques petits problèmes avec elle.
Dans cette version, j'ai permis au consommateur de spécifier les champs à exclure et également, par défaut, d'exclure toute propriété associée à une base de données ou à un modèle.
public static T Transform<T>(this object myobj, string excludeFields = null)
{
// Compose a list of unwanted members
if (string.IsNullOrWhiteSpace(excludeFields))
excludeFields = string.Empty;
excludeFields = !string.IsNullOrEmpty(excludeFields) ? excludeFields + "," : excludeFields;
excludeFields += $"{nameof(DBTable.ID)},{nameof(DBTable.InstanceID)},{nameof(AuditableBase.CreatedBy)},{nameof(AuditableBase.CreatedByID)},{nameof(AuditableBase.CreatedOn)}";
var objectType = myobj.GetType();
var targetType = typeof(T);
var targetInstance = Activator.CreateInstance(targetType, false);
// Find common members by name
var sourceMembers = from source in objectType.GetMembers().ToList()
where source.MemberType == MemberTypes.Property
select source;
var targetMembers = from source in targetType.GetMembers().ToList()
where source.MemberType == MemberTypes.Property
select source;
var commonMembers = targetMembers.Where(memberInfo => sourceMembers.Select(c => c.Name)
.ToList().Contains(memberInfo.Name)).ToList();
// Remove unwanted members
commonMembers.RemoveWhere(x => x.Name.InList(excludeFields));
foreach (var memberInfo in commonMembers)
{
if (!((PropertyInfo)memberInfo).CanWrite) continue;
var targetProperty = typeof(T).GetProperty(memberInfo.Name);
if (targetProperty == null) continue;
var sourceProperty = myobj.GetType().GetProperty(memberInfo.Name);
if (sourceProperty == null) continue;
// Check source and target types are the same
if (sourceProperty.PropertyType.Name != targetProperty.PropertyType.Name) continue;
var value = myobj.GetType().GetProperty(memberInfo.Name)?.GetValue(myobj, null);
if (value == null) continue;
// Set the value
targetProperty.SetValue(targetInstance, value, null);
}
return (T)targetInstance;
}
var obj = _account.Retrieve(Email, hash);
AccountInfoResponse accountInfoResponse = new AccountInfoResponse();
if (obj != null)
{
accountInfoResponse =
JsonConvert.
DeserializeObject<AccountInfoResponse>
(JsonConvert.SerializeObject(obj));
}