Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/313.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用通用接口的非通用部分_C#_Generics_Reflection_Interface - Fatal编程技术网

C# 使用通用接口的非通用部分

C# 使用通用接口的非通用部分,c#,generics,reflection,interface,C#,Generics,Reflection,Interface,考虑以下代码: public interface IStuff<T> { IList<T> Items { get; set; } bool IsExpanded { get; set; } } public interface IBar { string Name { get; set; } } public interface IFoo : IBar, IStuff<IBar> { } public class MyClass

考虑以下代码:

public interface IStuff<T>
{
    IList<T> Items { get; set; }
    bool IsExpanded { get; set; }
}

public interface IBar
{
    string Name { get; set; }
}

public interface IFoo : IBar, IStuff<IBar>
{
}

public class MyClass : IFoo 
{
    public Name {get;set;
    public IList<IBar> Items { get; set;}
    bool IsExpanded { get; set; }
}
这里的问题是,强制转换成
IStuff
现在不起作用,它返回null。 我想做的是只处理接口的通用部分,我不关心
t
是什么

问题是我该如何替换

IStuff<object> stuff = item as IStuff<object>;
IStuff stuff=作为IStuff的项目;
这样我就可以使用
IStuff
界面中声明的项了?

听起来像是您需要在界面上使用
IStuff
。但是,由于
IList
不是协变量,您可以使用支持协方差的接口,例如
IEnumerable
,它是自.NET 4.0以来的协变量:

public interface IStuff<out T>
{
    IEnumerable<T> Items { get; set; }
    bool IsExpanded { get; set; }
}
公共接口IStuff
{
IEnumerable Items{get;set;}
布尔IsExpanded{get;set;}
}
现在,您可以将
IStuff
的实例强制转换为
IStuff

听起来像是在界面上需要的
IStuff
。但是,由于
IList
不是协变量,您可以使用支持协方差的接口,例如
IEnumerable
,它是自.NET 4.0以来的协变量:

public interface IStuff<out T>
{
    IEnumerable<T> Items { get; set; }
    bool IsExpanded { get; set; }
}
公共接口IStuff
{
IEnumerable Items{get;set;}
布尔IsExpanded{get;set;}
}

现在,您可以将
IStuff
的实例强制转换为
IStuff

您可以将
IStuff
拆分为非泛型部分和泛型部分(继承自非泛型部分),然后只处理代码中的非泛型部分吗?例如

public interface IStuff
{
    IsExpanded { get; set; }
}
public interface IStuff<T> : IStuff
{
    IList<T> Items { get; set; }
}
公共接口IStuff
{
IsExpanded{get;set;}
}
公共接口IStuff:IStuff
{
IList项{get;set;}
}

能否将
IStuff
拆分为非通用部分和通用部分(继承自非通用部分),然后只处理代码中的非通用部分?例如

public interface IStuff
{
    IsExpanded { get; set; }
}
public interface IStuff<T> : IStuff
{
    IList<T> Items { get; set; }
}
公共接口IStuff
{
IsExpanded{get;set;}
}
公共接口IStuff:IStuff
{
IList项{get;set;}
}

如果不介意反射,可以读取属性并将其强制转换为
IEnumerable

var listType = item.GetType().GetProperty("Items");
var enumerable = (IEnumerable)(listType.GetValue(item));

同样,您可以设置扩展标志。

如果您不介意反射,您可以读取属性并将其强制转换为
IEnumerable

var listType = item.GetType().GetProperty("Items");
var enumerable = (IEnumerable)(listType.GetValue(item));

同样,您可以设置扩展标志。

也许您应该将接口分为两个版本,一个通用版本和一个非通用版本,其中通用版本继承非通用版本。然后,您可以在不知道
的情况下使用对象,但当然您只能访问不需要
T
@himbrombeer的东西。您已经解决了这个问题。也许您应该将界面分为两个,一个通用版本和一个非通用版本,其中通用版本继承自非通用版本。然后,您可以在不知道
的情况下使用对象,但当然,您只能访问不需要
T
@himbrombee的东西。我们为您解决了这个问题。不幸的是,我不能这样做。我想做的是在树视图的控件中使用IStuff,项目将成为链接到孩子们的部分。不幸的是,我不能这样做。我想做的是在树视图的控件中使用IStuff,Items将成为链接到子级的部分。这很有希望,目前接口看起来还不错,但是,我无法将MyClass更改为声明IEnumerable。它必须是一个列表。这是因为还有一个我没有提到的实现需要一个列表。我还需要能够添加项等等。但是您可以在类上实现该接口,并重定向到
MyClass.items
,这样您就有了
IStuff.items
,它返回一个
IEnumerable
,需要明确声明,还有
MyClass.items
,它返回一个
IList
。这不会改变
MyClass
的API,它会通过更改的接口启用它。我仍然在关注这一点,看起来非常有希望。只是有很多其他代码正在实现ICollection,我需要修改它们才能编译。我还希望集合最终包装在类中。也许您可以创建一个支持
IEnumerable
的新接口,并在类中实现
IFoo
-接口和新接口。当然,类上新接口的实现只是重定向到已经存在的方法。我现在已经了解了项目,因此应该可以使用iExpanded和项目以及我将要添加到接口的其他内容。我喜欢这个解决方案中也不需要反射。这很有希望,接口目前看起来还不错,但是,我不能将MyClass更改为声明IEnumerable。它必须是一个列表。这是因为还有一个我没有提到的实现需要一个列表。我还需要能够添加项等等。但是您可以在类上实现该接口,并重定向到
MyClass.items
,这样您就有了
IStuff.items
,它返回一个
IEnumerable
,需要明确声明,还有
MyClass.items
,它返回一个
IList
。这不会改变
MyClass
的API,它会通过更改的接口启用它。我仍然在关注这一点,看起来非常有希望。只是有很多其他代码正在实现ICollection,我需要修改它们才能编译。我还希望集合最终包装在类中。也许您可以创建一个支持
IEnumerable
的新接口,并在类中实现
IFoo
-接口和新接口。当然,类上新接口的实现只是重定向到已经存在的方法。我现在要处理这些项目,c也应该这样做