2010-09-08 21 views
20

câu hỏi của tôi được thể hiện trong mã nàylớp diễn viên vào lớp học khác hoặc chuyển đổi lớp khác

tôi có lớp học như thế

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

Mã này không có ý nghĩa. Mã bưu điện biên dịch (nó không phải là diễn viên đó là vấn đề). –

+7

Khá khắc nghiệt .. Thiếu một từ khóa 'lớp' không mang ý nghĩa đi. – nawfal

+0

Hiện có các thư viện bản đồ nhẹ có sẵn được viết cho mục đích chính xác này. Họ xử lý nhiều trường hợp cạnh hơn. Bạn có thể google nó. – nawfal

Trả lời

23

gì ông muốn nói là:

"Nếu bạn có hai lớp mà chia sẻ hầu hết các tính chất tương tự bạn có thể cast một đối tượng từ lớp a đến lớp b và tự động làm cho hệ thống hiểu được nhiệm vụ thông qua chia sẻ tên thuộc tính? "

Tùy chọn 1: Sử dụng phản chiếu

Bất lợi: Nó sẽ làm chậm bạn nhiều hơn bạn nghĩ.

Tùy chọn 2: Làm cho một lớp bắt nguồn từ một lớp khác, thuộc tính đầu tiên có thuộc tính chung và phần mở rộng khác.

Bất lợi: Đã kết hợp! nếu bạn đang làm điều đó cho hai lớp trong ứng dụng của bạn thì hai lớp sẽ được ghép nối!

Let There Be:

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

Bây giờ đây là một phần mở rộng cho loại đối tượng:

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

Bây giờ bạn sử dụng nó như thế này: kiểm tra cast

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

Phương pháp tài sản chung giữa hai đối tượng và thực hiện nhiệm vụ tự động.

+1

Đó là những gì tôi có nghĩa là chính xác –

+0

Giải pháp tốt đẹp, nhưng như bạn đã nói, trên không và phức tạp :) – Noctis

+0

Tôi đoán bạn đã bỏ lỡ để sử dụng biến 'z'. Nó nên được sử dụng khi khởi tạo 'thành viên' var tức là Danh sách thành viên = z.Where (memberInfo => d.Select (c => c.Name) .ToList(). Chứa (memberInfo.Name)). ToList() ; – Aamol

5

Bạn có thể thay đổi cấu trúc lớp của bạn để:

public class maincs : sub1 
{ 
    public int d; 
} 

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

Sau đó, bạn có thể giữ một danh sách các sub1 và đúc một số trong số họ để mainc.

+0

Điều này cũng không biên dịch. Có thể bạn đã quên từ khóa 'class' –

+0

Rất tiếc, đó là những gì tôi nhận được để sao chép/dán. –

43

Bạn đã xác định chuyển đổi, bạn chỉ cần thực hiện chuyển đổi thêm một bước nếu bạn muốn có thể truyền. Ví dụ:

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

Mà sau đó cho phép bạn làm điều gì đó như

static void Main() 
{ 
    sub1 mySub = new sub1(); 
    maincs myMain = (maincs)mySub; 
} 
+2

Thậm chí còn tốt hơn câu trả lời được chọn – Noctis

+1

Câu trả lời hay. Cảm ơn. – Ellis

+0

Có bất kỳ ý nghĩa nào để chuyển đổi/truyền từ lớp này sang lớp khác với các đạo cụ chính xác bằng cách sử dụng mã của bạn không? – Code

2

Bạn có thể cung cấp một quá tải rõ ràng cho các nhà điều hành dàn diễn viên:

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

Một lựa chọn khác là sử dụng một giao diện có thuộc tính a, b và c và triển khai giao diện trên cả hai lớp. Sau đó, chỉ cần có kiểu tham số cho phương thức là giao diện thay vì lớp.

1

Bằng cách sử dụng mã sau, bạn có thể sao chép bất kỳ đối tượng lớp nào vào đối tượng lớp khác cho cùng tên và cùng loại thuộc tính.

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

Gọi Phương pháp Giống như,

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

CopyClass.CopyObject(objOfferMast, ref objB); 

Nó sẽ sao chép objA vào objB.

+1

Xin lưu ý rằng nếu bạn đang sử dụng giải pháp này, bạn có thể gặp sự cố khi các lớp có cùng tên cho thuộc tính, nhưng với các loại khác nhau. Ví dụ: 'public class A {public int Age {get; set;}}' và 'public class B {public string Age {get; set;}}' Sẽ ném một ngoại lệ, nếu bạn đang cố gắng chuyển đổi từ 'A' đến' B' – Noctis

+0

Loại chuyển đổi này cũng có thể dẫn đến một số vấn đề hiệu suất lớn. Sử dụng nó một cách cẩn thận và chắc chắn không có trong vòng lặp – RPDeshaies

11

Một lựa chọn khác là sử dụng JSON serialization và deserialization:

using Newtonsoft.Json; 

Class1 obj1 = new Class1(); 
Class2 obj2 = JsonConvert.DeserializeObject<Class2>(JsonConvert.SerializeObject(obj1)); 

Hoặc:

public class Class1 
{ 
    public static explicit operator Class2(Class1 obj) 
    { 
     return JsonConvert.DeserializeObject<Class2>(JsonConvert.SerializeObject(obj)); 
    } 
} 

Mà sau đó cho phép bạn làm điều gì đó như

static void Main() 
{ 
    Class1 obj1 = new Class1(); 
    Class2 obj2 = (Class2)obj1; 
} 
+1

Có, sử dụng serializer Newtonsoft json khá đơn giản và hiệu quả. Có serializer .Net nhưng tôi tìm thấy Newtonsoft làm tốt hơn. Net json serializer. Tôi tìm thấy liên kết này cung cấp một so sánh ngắn gọn http://www.newtonsoft.com/json/help/html/JsonNetVsDotNetSerializers.htm – Aamol

1

Có một số câu trả lời tuyệt vời ở đây, tôi chỉ muốn để thêm một chút kiểm tra kiểu ở đây vì chúng ta không thể giả định rằng nếu các thuộc tính tồn tại có cùng tên, chúng có cùng kiểu. Đây là lời đề nghị của tôi, mở rộng về câu trả lời trước đó, rất tuyệt vời khi tôi có một chút trục trặc với nó.

Trong phiên bản này, tôi đã cho phép người tiêu dùng chỉ định các trường cần loại trừ và cũng theo mặc định để loại trừ bất kỳ cơ sở dữ liệu/mô hình đặc tính liên quan cụ thể nào.

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; 
    } 
Các vấn đề liên quan