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也应该这样做