我有100个类,它们有一些相似的元素和一些独特的元素。我创建了一个界面来命名那些相似的项目,例如:interface IAnimal。我通常会做的是:
class dog : IAnimal
但是有100个课程,我不觉得他们全部都在寻找那些可以应用IAnimal的课程。
我想做的是:
dog scruffy = new dog();
cat ruffles = new cat();
IAnimal[] animals = new IAnimal[] {scruffy as IAnimal, ruffles as IAnimal} // gives null
或
IAnimal[] animals = new IAnimal[] {(IAnimal)scruffy, (IAnimal)ruffles} //throws exception
然后做
foreach (IAnimal animal in animals)
{
animal.eat();
}
有没有办法让c#让我把褶边和scruffy作为一个IAnimal而不必写:IAnimal在写这个类时。
谢谢!
编辑(不是懒惰):这些类是从sql存储的proc元数据生成的,这意味着每次生成它时我都必须返回并添加它们,或者修改代码生成器以识别其中的成员接口,实际上这不是一个坏主意。我希望有某种泛型方法或者其他东西。
答案 0 :(得分:10)
你要求的是鸭子打字而不是C#的一部分我害怕。任何解决方案都将涉及反思和查看属性,我认为手动检查类会更快。
尝试这将是一个有趣的项目。
答案 1 :(得分:6)
你可以用部分类解决这个问题:让机器生成/重新生成的代码放在每个类的一个源文件中,手工编码的部分(从IAnimal定义子类)另一个。
答案 2 :(得分:4)
解决方案是修改代码生成器。目前,它太简单了,无法满足您的需求。如果类中存在相关属性和/或方法,则应添加接口实现。
答案 3 :(得分:4)
你可以创建一个通过反射访问“eat
”的适配器,一个穷人的鸭子打字:
public class Adapter<T> : IAnimal
{
private T x;
Adapter(T x)
{
this.x = x;
}
public void eat()
{
x.GetType().GetMethod("eat").Invoke(this);
}
}
然后你可以像这样使用它:
dog scruffy = new dog();
cat ruffles = new cat();
IAnimal[] animals = new IAnimal[] {new Adapter<dog>(scruffy), new Adapter<cat>(ruffles )};
答案 4 :(得分:1)
假设你真的无法修改cat类,原因很充分,
您可以编写一个继承自IAnimal的cat适配器,即:
class cat_adapter : IAnimal
{
private cat baseCat;
public cat_adapter( cat aCat)
{
baseCat = aCat;
}
// Implement IAnimal interface and redirect to baseCat
public void eat()
{
baseCat.munchOnMeowMix();
}
}
在C ++中,您可以使用模板,假设您生成的所有类都需要具有相同的函数:
template <class BaseType>
class CAnimalAdapter : public IAnimal
{
private:
BaseType* m_baseInstance;
public:
CAnimalAdapter(BaseType* baseInstance) :
m_baseInstance(baseInstance)
{
}
void eat()
{
// You will get a compiler error if BaseType doesn't have this implemented
baseInstance->doEat();
}
}
也许有人比我更喜欢C#-py可以用反射来做同样的事情。
答案 5 :(得分:1)
我不清楚,你可以使用反射进行后期绑定调用,但你最好花时间编辑类或编写宏来执行它。
答案 6 :(得分:1)
如果代码生成器将类生成为partial,则可以添加另一个实现接口的部分定义。
答案 7 :(得分:0)
没有。如果没有具体的基类或有接口,就无法让C#让你这样做。
答案 8 :(得分:0)
如果您已经实现了该方法并且只想实现该接口,则可以在IDE中使用带有replace in files命令的正则表达式。
否则,请看一下扩展方法。它们可能符合您的需求。
答案 9 :(得分:0)
您的类必须实现IAnimal接口。除非它们都是接口/基类的实现,否则两个不同类上的同名方法/属性不被视为等效。
答案 10 :(得分:0)
如果将生成的类实现为部分类,则可以在这些类上实现接口,然后将代码生成器更改为仅生成部分类的一半。这将允许您重新生成类而不会丢失接口实现(或您决定添加的任何其他自定义逻辑)。
这种方法是LINQ to SQL如何生成类文件。