简体   繁体   English

访问继承的泛型类的泛型属性

[英]Access to generic property of inherited generic class

Related to: C# - Multiple generic types in one list and Access to property of inherited generic class 有关于: C#-一个列表中有多个泛型类型,并且可以访问继承的泛型类的属性

Please consider this code: 请考虑以下代码:

public abstract class Metadata
{
}

public class Metadata<T> : Metadata
{
    public List<T> MyCollection{set; get;}
}

public class MetaDataCollection
{
    public void DoSomeThing()
    {
        List<Metadata> metadataObjects = new List<Metadata>
        {
            new Metadata<int>() { MyCollection = new List<int>()},
            new Metadata<bool>() { MyCollection = new List<bool>()},
            new Metadata<double>() { MyCollection = new List<double>()},
        };

        foreach(vat item in metadataObjects)
        {
            item.MyCollection??????
        }
    }
}

in above code how I can access to MyCollection property? 在上面的代码中,我如何访问MyCollection属性?

Thanks 谢谢

It's not elegant, but you could lookup the generic type argument and cast accordingly as below. 这不是很优雅,但是您可以查找泛型类型参数并按如下所示进行相应的转换。

public class MetaDataCollection
{
    public void DoSomeThing()
    {
        List<Metadata> metadataObjects = new List<Metadata>
        {
            new Metadata<int>() { MyCollection = new List<int>() { 1, 2, 3, 4} },
            new Metadata<bool>() { MyCollection = new List<bool>() { true, false, false} },
            new Metadata<double>() { MyCollection = new List<double>() { 1.5, 2.1 } },
        };

        Dictionary<Type, Action<Metadata>> actionLookup = new Dictionary<Type, Action<Metadata>>()
        {
            { typeof(int), (meta) => Console.WriteLine(((Metadata<int>)meta).MyCollection[0]) },
            { typeof(bool), (meta) => Console.WriteLine(((Metadata<bool>)meta).MyCollection[0]) },
            { typeof(double), (meta) => Console.WriteLine(((Metadata<double>)meta).MyCollection[0]) }
        };

        foreach (var item in metadataObjects)
        {
            Type metaDataType = item.GetType().GenericTypeArguments.First();
            actionLookup[metaDataType](item);
        }
    }
}

You could fix it like List<> https://docs.microsoft.com/en-us/dotnet/api/system.collections.generic.list-1 does it. 您可以像List<> https://docs.microsoft.com/en-us/dotnet/api/system.collections.generic.list-1这样来修复它。

//use interfaces instead of abstract class
public interface IMetadata
{
    List<object> MyCollection { get; set; }
}

public interface IMetadata<T>
{
    List<T> MyCollection { get; set; }
}

//as List<> the List and List<> don't derive from each other but instead have a common interface the non-generic IList
public class Metadata : IMetadata
{
    public List<object> MyCollection { get; set; }
}

//implement the generic and non-generic interface
public class Metadata<T> : IMetadata<T>, IMetadata
{
    public List<T> MyCollection { get; set; }

    //hide the non-generic interface member MyCollection
    List<object> IMetadata.MyCollection { get { return this.MyCollection.Cast<object>().ToList(); } set { this.MyCollection = value.Cast<T>().ToList(); } }

}

public class MetaDataCollection
{
    public void DoSomeThing()
    {
        //make a list of IMetadata
        List<IMetadata> metadataObjects = new List<IMetadata>
        {
            new Metadata<int>() { MyCollection = new List<int>()},
            new Metadata<bool>() { MyCollection = new List<bool>()},
            new Metadata<double>() { MyCollection = new List<double>()},
        };

        foreach (var item in metadataObjects)
        {
            //item.MyCollection is now a List<object>
        }
    }
}

the code below breaks OOP ideology and rules, but it will achieve the aim. 下面的代码打破了OOP的思想和规则,但可以达到目的。 And be ware of exceptions 并提防异常

        foreach(dynamic item in metadataObjects)
        {
            Console.WriteLine(item.MyCollection.Count);
        }

you must check your Item type and then cast it into a suitable MetaData: 您必须检查Item类型,然后将其转换为合适的MetaData:

public abstract class Metadata
{
}

public class Metadata<T> : Metadata
{
    public List<T> MyCollection { set; get; }
}

public class MetaDataCollection
{
    public void DoSomeThing()
    {
        List<Metadata> metadataObjects = new List<Metadata>
    {
        new Metadata<int>() { MyCollection = new List<int>()},
        new Metadata<bool>() { MyCollection = new List<bool>()},
        new Metadata<double>() { MyCollection = new List<double>()},
    };

        foreach (var item in metadataObjects)
        {
            if (item is Metadata<int>)
            {
                var intItem = item as Metadata<int>;
                intItem.Add(10);
            }
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM