如果我有以下方法;
private TSource CopyFileClientModel<TSource>(TSource fileClientOrContact)
因此,我可以使用FileClient
或FileContact
模型传入此方法。
两者都有一个名为Contact
的属性,它也是一个模型以及两者之间不常见的其他属性。
现在我想从传入的模型中获取Contact
模型。
Contact sourceContact = fileClientOrContact.Contact;
但是,鉴于这是通用的,它不知道Contact
中有TSource
个对象。
我的限制是我无法针对FileClient
或FileContact
设置界面。我基本上无法触及这些模型。
如何从TSource
获取联系人对象?我可以用某种方式使用反射吗?
答案 0 :(得分:2)
您可以使用Visitor pattern来包装这两个类,并让两个访问者类继承自公共接口。
基本上,您将创建一个具有FileClient
或FileContact
的重复方法/属性的新类,并在构造函数中传递该类的实例。所有方法和属性都链接到您正在存储的类实例中的实际方法和属性。您的两个访问者类都将具有Contact
属性,因此您可以告诉访问者类从公共接口继承。
答案 1 :(得分:2)
如果使用.NET 4,则可以使用dynamic:
private TSource CopyFileClientModel<TSource>(TSource fileClientOrContact)
(
dynamic d = fileClientOrContact;
// Now you reach the Contact property
var x = d.Contact;
)
明智的做法是验证typeof(TSoruce)
是FileClient
还是FileContact
你可以做的另一件事是包装这两个类。请参阅维基百科中的adapter design pattern
但也许Generics
不是你的解决方案。为什么不在FileClient
和FileContact
使用Method重载。你的方法签名接受任何TSource,但是当方法得到int,long,Person它无效时,如果你可以将Generics
限制为你期望的类型,那么TSource
不是正确的解决方案
请改用Method overload
。并保存那些“创意解决方案”
答案 2 :(得分:2)
您可以传递函数以返回联系人。
例如:
private FileClient CopyFileClientModel(FileClient fileClient) {
return this.CopyFileClientModel(fileClient, c => c.Client);
}
private FileContact CopyFileClientModel(FileContact fileContact) {
return this.CopyFileClientModel(fileContact, c => c.Client);
}
private TSource CopyFileClientModel<TSource>(TSource fileClientOrContact, Func<TSource, Contact> contactGetter) {
var contact = contactGetter(fileClientOrContact);
// Whatever else...
}
答案 3 :(得分:1)
喜欢什么?
if (fileClientorContact is FileContact)
return fileClientorContact as Contact;
else
return ((Client)fileClientorContact).Contact;
当然,这假设fileClientorContact中的“联系人”与您要返回的类型相同。或者,如果两种类型都按照您在问题中的建议定义Contact
属性,则可以使用以下内容:
var propInfo = fileClientorContact.GetType().GetProperty("Contact");
if (propInfo == null)
return false; // replace with something appropriate
return propInfo.GetValue(fileClientorClient, null, null, null) as Contact;
大致来自记忆,但这个想法应该是有效的。
答案 4 :(得分:1)
如果您使用的是C#4.0,则可以使用动态
dyanmic obj = fileClientOrContact;
Contact sourceContact = obj.Contact;
但这并不理想! (它可能导致运行时异常)
修改强>
或者,我可能会为每种类型使用两个重载函数,每个函数调用共享功能的公共函数。
答案 5 :(得分:0)
如果FileContact
和FileClient
没有共享.Contact
的祖先,并且您无法为其实现公共接口,并且您真的想要使用反射,那么您可以做像这样的东西:
var sourceProp = typeof(TSource).GetProperty("Source");
Contact contact;
if(sourceProp != null)
{
contact = (Contact)sourceProp.getValue(fileClientOrContact, null)
}