我有一个具有一个类型参数(T)的泛型类.我需要存储这些不同类型的通用对象的集合,因此我创建了一个通用类实现的接口,如此处所示.在迭代通过包含Interface对象集合的泛型列表时,我需要访问类型T的泛型类中的属性.到目前为止,我能够获得该值的唯一方法是使用反射调用方法.
interface ISomeClass {
//?
}
class SomeClass<T> : ISomeClass {
T ValueINeed { get; set;}
}
class ClassThatHasListOfGenericObjects{
List<ISomeClass> _l = new List<ISomeClass>();
public AddToList<T>(T someClass) : where T : ISomeClass {
_l.Add(someClass);
}
public SomeMethod(){
foreach(ISomeClass i in _l){
i.ValueINeed; //I don't know how to access the property in the generic class
}
}
}
Run Code Online (Sandbox Code Playgroud)
我认为你有两种选择.简单的选择是在接口上公开值(作为对象)(也可能是它的类型).这是看起来如何:
interface ISomeClass
{
object ValueINeed { get; set; }
// Only needed if you care about static type rather than using ValueINeed.GetType()
Type TypeOfValue { get; }
}
class SomeClass<T> : ISomeClass
{
public T ValueINeed { get; set; }
public Type TypeOfValue { get { return typeof(T); } }
object ISomeClass.ValueINeed { get { return ValueINeed; } set { ValueINeed = (T)value; } }
}
Run Code Online (Sandbox Code Playgroud)
这样做有一个缺点,就是会进行一些强制转换,你可能需要调用反射来对值进行某些操作.它的优点是易于理解和实施.
另一种选择是编码一个"存在类型",它真正代表SomeClass<T>
一些未知的T
(如SomeClass<?>
Java中的).这更复杂,更难以遵循,但避免任何演员:
interface ISomeClassUser<X>
{
X Use<T>(SomeClass<T> s);
}
interface ISomeClassUser
{
void Use<T>(SomeClass<T> s);
}
interface ISomeClass
{
X Apply<X>(ISomeClassUser<X> user);
void Apply(ISomeClassUser user);
}
class SomeClass<T> : ISomeClass
{
public T ValueINeed { get; set; }
public X Apply<X>(ISomeClassUser<X> user) { return user.Use(this); }
public void Apply(ISomeClassUser user) { user.Use(this); }
}
// Assumes you want to get a string out, use a different generic type as needed
class XmlUser : ISomeClassUser<string>
{
public string Use<T>(SomeClass<T> s)
{
string str = "";
// do your conditional formatting here, branching on T as needed
// ...
return str;
}
}
class ClassThatHasListOfGenericObjects
{
List<ISomeClass> _l = new List<ISomeClass>();
XmlUser user = new XmlUser();
public string SomeMethod()
{
string s = "";
foreach (ISomeClass i in _l)
{
s += i.Apply(user);
}
return s;
}
}
Run Code Online (Sandbox Code Playgroud)