将类转换为另一个类或将类转换为另一个类

时间:2010-09-08 23:40:38

标签: c# casting class type-conversion

我的问题显示在此代码中

我有类似的课

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;    
}

10 个答案:

答案 0 :(得分:53)

您已经定义了转换,如果您希望能够投射,只需要更进一步。例如:

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;
    }
}

然后允许您执行类似

的操作
static void Main()
{
    sub1 mySub = new sub1();
    maincs myMain = (maincs)mySub;
}

答案 1 :(得分:31)

他想说的是:

“如果你有两个共享大多数相同属性的类,你可以将一个对象从类a转换为类b,并自动使系统通过共享属性名称理解赋值?”

选项1:使用反射

缺点:它会比你想象的更慢。

选项2:使一个类派生自另一个,第一个具有共同属性,另一个具有扩展属性。

缺点:加上!如果您在应用程序中为两层执行此操作,则两个层将耦合!

让我们:

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; } 
}

现在这里是对象类型的扩展名:

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;
}  

现在你这样使用它:

static void Main(string[] args)
{
    var cus = new customer();
    cus.firstname = "John";
    cus.age = 3;
    employee emp =  cus.Cast<employee>();
}

方法转换检查两个对象之间的公共属性并自动执行赋值。

答案 2 :(得分:31)

使用JSON序列化和反序列化:

void hashAdd(char * data, struct listnode * hashTable[], int size){
    int key=hash(data, size);
    if (hashTable[key]->word == NULL) {
        // First time with this key
        hashTable[key]->word=strdup(data);
        hashTable[key]->count+=1;
     } else {
         // Key already used once
         if (strcmp(data, hashTable[key]->word) == 0) {
             // Same word
             hashTable[key]->count+=1;
         } else {
             // Different word
             // ...
             // Add code for storing this word in another location
             // ...
         }
     }
}

或者:

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));
    }
}

答案 3 :(得分:5)

您可以将班级结构更改为:

public class maincs : sub1
{
   public int d; 
}

public class sub1
{
   public int a;
   public int b;
   public int c;
}

然后你可以保留一个sub1列表并将其中一些转换为mainc。

答案 4 :(得分:2)

您可以为强制转换操作符提供显式重载:

public static explicit operator maincs(sub1 val)
{
    var ret = new maincs() { a = val.a, b = val.b, c = val.c };
    return ret;
}

另一种选择是使用具有a,b和c属性的接口,并在两个类上实现接口。然后让methoda的参数类型成为接口而不是类。

答案 5 :(得分:1)

通过使用以下代码,您可以将任何类对象复制到另一个类对象,以获得相同名称和相同类型的属性。

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);
        }
    }
}

Call Method Like,

ClassA objA = new ClassA();
ClassB objB = new ClassB();

CopyClass.CopyObject(objOfferMast, ref objB);

它会将objA复制到objB

答案 6 :(得分:1)

这里有一些很好的答案,我只想在这里添加一些类型检查,因为我们不能假设如果属性存在同名,那么它们属于同一类型。这是我的产品,它延续了之前非常优秀的答案,因为我有一些小问题。

在此版本中,我允许使用者指定要排除的字段,并且默认情况下也排除任何数据库/模型特定的相关属性。

    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;
    }

答案 7 :(得分:1)

使用此代码,您可以将任何具有相同名称和相同类型属性的类对象复制到另一个类对象。

JavaScriptSerializer JsonConvert = new JavaScriptSerializer(); 
string serializeString = JsonConvert.Serialize(objectEntity);
objectViewModel objVM = JsonConvert.Deserialize<objectViewModel>(serializeString);

答案 8 :(得分:0)

var obj =  _account.Retrieve(Email, hash);

AccountInfoResponse accountInfoResponse = new AccountInfoResponse();

if (obj != null)
{               
   accountInfoResponse = 
   JsonConvert.
   DeserializeObject<AccountInfoResponse>
   (JsonConvert.SerializeObject(obj));
}

image description

答案 9 :(得分:0)

在目标类型包含源类型中不存在的属性的情况下,我尝试使用 Cast Extension(请参阅 https://stackoverflow.com/users/247402/stacker)。它没有用,我不知道为什么。我重构为以下对我的情况有效的扩展:

public static T Casting<T>(this Object source)
{
    Type sourceType = source.GetType();
    Type targetType = typeof(T);
    var target =  Activator.CreateInstance(targetType, false);
    var sourceMembers = sourceType.GetMembers()
        .Where(x => x.MemberType  == MemberTypes.Property)
        .ToList();
    var targetMembers = targetType.GetMembers()
        .Where(x => x.MemberType == MemberTypes.Property)
        .ToList();
    var members = targetMembers
        .Where(x => sourceMembers
            .Select(y => y.Name)
                .Contains(x.Name));
    PropertyInfo propertyInfo;
    object value;
    foreach (var memberInfo in members)
    {
        propertyInfo = typeof(T).GetProperty(memberInfo.Name);
        value = source.GetType().GetProperty(memberInfo.Name).GetValue(source, null);
        propertyInfo.SetValue(target, value, null);
    }
    return (T)target;
}

请注意,我更改了扩展名,因为 Name Cast 与来自 Linq 的结果冲突。帽子提示https://stackoverflow.com/users/2093880/usefulbee