从通用类实现的接口调用泛型类中的泛型属性

dug*_*gas 2 c# generics

我有一个具有一个类型参数(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)

kvb*_*kvb 5

我认为你有两种选择.简单的选择是在接口上公开值(作为对象)(也可能是它的类型).这是看起来如何:

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)