C# 通用接口列表

C# 通用接口列表,c#,generics,interface,C#,Generics,Interface,如果我有一个带有几个实现类的通用接口,例如: public interface IDataElement<T> { int DataElement { get; set; } T Value { get; set; } } public class IntegerDataElement : IDataElement<int> { public int DataElement { get; set; } public int Value {

如果我有一个带有几个实现类的通用接口,例如:

public interface IDataElement<T>
{
    int DataElement { get; set; }
    T Value { get; set; }
}

public class IntegerDataElement : IDataElement<int>
{
    public int DataElement { get; set; }
    public int Value { get; set; }
}

public class StringDataElement : IDataElement<String>
{
    public int DataElement { get; set; }
    public String Value { get; set; }
}
公共接口IDataElement
{
int数据元素{get;set;}
T值{get;set;}
}
公共类整型数据元素:IDataElement
{
公共int数据元素{get;set;}
公共int值{get;set;}
}
公共类StringDataElement:IDataElement
{
公共int数据元素{get;set;}
公共字符串值{get;set;}
}
可以传递不同类型的实现类的集合,而不必作为对象传递

似乎不可能将返回值定义为

public IDataElement<T>[] GetData()
public-IDataElement[]GetData()

public-IDataElement[]GetData()

有什么建议吗?

您当然可以声明:

public IDataElement<T>[] GetData<T>()
这在你的特殊情况下有用吗


不清楚在不知道数据元素类型的情况下,您希望如何使用数据元素集合。。。如果上述内容对您没有帮助,也许您可以进一步说明您希望如何处理这些集合。

不,您不能这样做-唯一的选择是使用非通用接口:

public interface IDataElement
{
    int DataElement { get; set; }
}

public interface IDataElement<T> : IDataElement
{
    T Value { get; set; }
}
public interface IDataElement
{
    int DataElement { get; set; }
    object Value { get; set; }
}
或者,创建包装器并将其传递给了解所需类型的方法:

public class DataElementBag
{
    private IDictionary<Type, List<object>> _elements;
    ...
    public void Add<T>(IDataElement<T> de)
    {
        Type t = typeof(T);
        if(!this._elements.ContainsKey(t))
        {
            this._elements[t] = new List<object>();
        }

        this._elements[t].Add(de);
    }

    public void IEnumerable<IDataElement<T>> GetElementsByType<T>()
    {
        Type t = typeof(T);
        return this._elements.ContainsKey(t)
            ? this._elements[t].Cast<IDataElement<T>>()
            : Enumerable.Empty<T>();
    }
}
公共类DataElementBag
{
私有索引元素;
...
公共无效添加(IDataElement de)
{
类型t=类型(t);
如果(!this._elements.ContainsKey(t))
{
此._元素[t]=新列表();
}
此._元素[t].添加(de);
}
public void IEnumerable GetElementsByType()
{
类型t=类型(t);
返回此。\u elements.ContainsKey(t)
?此._元素[t].Cast()
:Enumerable.Empty();
}
}

不确定这是否有助于您的用例,但您可以创建一个没有任何内容的基本/标记接口

public interface IDataElement {}
并让您的变体通用接口继承自该接口(如Jon Skeet所示)

公共接口IDataElement
因此,您可以创建这些“对象”的集合,并使用其反变、非变的通用接口(多丰满的嘴啊)

var collection=new List(){…}
我想,当你使用一个元素时,你可能需要有点明确,但对我来说,这就是C#Type safety的意义所在(C#非常明确!),并避免使用对象

IDataElement<MyType> value = List.First(x => DataElement == 12);
IDataElement value=List.First(x=>DataElement==12);
或者使用稍微皱眉的显式演员阵容

var element = (IDataElement<MyType>)List.First(x => DataElement == 12);
var-element=(IDataElement)列表。第一个(x=>DataElement==12);
我之所以搜索这个问题,是因为我有一个像
TTYpe Get()
这样的通用方法,因为我有点搞砸了策略/访问者模式。我想通过使用泛型类型作为方法的参数,向我的提供者询问一件任意的事情

听起来可能有点奇怪,但实际上我可以利用依赖项注入来注入任意数量的IDataElement实现,这些实现知道如何根据提供程序自行配置它们。。。我想做的就是

var sqlConnection = tenantProvider.Get<SqlConnection>();
var storageTyep = tenantProvider<StorageProvider>();
var-sqlConnection=tenantProvider.Get();
var storageTyep=tenantProvider();
借助泛型、变量泛型接口和标记接口的强大功能。。它工作得很好。在使用者处强类型,完成泛型实现

 public TSetting GetSetting<TSetting>() where TSetting : class
 {
        var sp = tenantSettingsDictionary[typeof(TSetting)];
        return sp as TSetting;
 }
public TSetting GetSetting(),其中TSetting:class
{
var sp=租户设置字典[类型(设置)];
将sp返回为TSetting;
}

我尝试了非泛型基类,但它丢失了值的细节property@benPearce:但无论如何,您都不能使用它,因为您不知道所涉及的类型。请尝试演示如何使用代码,然后我们可以给您提供更好的建议。最后,我使用object GetValue()和SetValue(object)方法访问了非通用的基本接口。这样工作far@JonSkeet,我在哪里可以找到结构不支持协方差的原因?有很好的理由,但现在还不能想出一个:(@Erti ChrisEelmaa:看到了吗
IDataElement<MyType> value = List.First(x => DataElement == 12);
var element = (IDataElement<MyType>)List.First(x => DataElement == 12);
var sqlConnection = tenantProvider.Get<SqlConnection>();
var storageTyep = tenantProvider<StorageProvider>();
 public TSetting GetSetting<TSetting>() where TSetting : class
 {
        var sp = tenantSettingsDictionary[typeof(TSetting)];
        return sp as TSetting;
 }