[英]Implementations of an Interface with Different Types?
我已尽力进行搜索,但不幸的是,我没有发现任何相关信息。 基本上我正在尝试解决C#中的以下问题...
例如,我有三个可能的引用(refA,refB,refC),我需要根据配置选项加载正确的引用。 但是到目前为止,我还看不到一种方法,不需要我在整个代码中都使用所述引用对象的名称(提供了引用对象,我无法更改它们)。 希望以下代码更有意义:
public ??? LoadedClass;
public Init()
{
/* load the object, according to which version we need... */
if (Config.Version == "refA")
{
Namespace.refA LoadedClass = new refA();
}
else if (Config.Version == "refB")
{
Namespace.refB LoadedClass = new refB();
}
else if (Config.Version == "refC")
{
Namespace.refC LoadedClass = new refC();
}
Run();
}
private void Run(){
{
LoadedClass.SomeProperty...
LoadedClass.SomeMethod(){ etc... }
}
如您所见,我需要Loaded类是公共的,因此我以有限的方式尝试在加载所需的真实类时“动态”更改类型。 refA,refB和refC中的每一个都将实现相同的属性和方法,但名称不同。 同样,这是我正在使用的内容,而不是我的设计。
所有这些,我试图绕过Interfaces(听起来像是我所追求的),但是我正在查看它们并看到严格的类型-这对我来说很有意义,即使它对我没有用。
欢迎任何想法和意见,如有必要,我将澄清。 请原谅我在术语上犯的任何愚蠢的错误,这是我第一次学习所有这些内容。 到目前为止,我真的很喜欢使用OOP语言-来自PHP的东西让我很惊讶:-)
编辑
抱歉,一点儿也没有清楚,但是refA,refB和refC的方法都有唯一的类型,即使它们在功能上本质上是相同的(想法是对它们进行版本控制)。 这意味着在我的脑海中,我剩下的是:
public interface IRef
{
SomeType<<RefA,RefB,RefC,???>> SomeProperty {get;}
void SomeMethod();
}
感谢GenericTypeTea作为起始接口点。 我可能正在尝试执行不建议/不可能执行的操作...根本的问题是我需要从同一程序支持不同版本(根据配置选项)。 否则我将为每个版本开发“不同的”程序,那简直是一团糟:-)
编辑2
public interface Sage
{
SageDataObject???.SDOEngine sdo;
}
class SageObj150 : Sage
{
SageDataObject150.SDOEngine sdo = new SageDataObject150.SDOEngine();
}
class SageObj160 : Sage
{
SageDataObject160.SDOEngine sdo = new SageDataObject160.SDOEngine();
}
class SageObj170 : Sage
{
SageDataObject170.SDOEngine sdo = new SageDataObject170.SDOEngine();
}
SDOEngine()(我刚刚才看过)本身就是一个接口-我认为这使事情非常混乱。 以为我在不了解C#的情况下编写整个应用程序就做得不错,但是现在看来这超出了我的Google技能。 在此先感谢大家的耐心配合!
除非我误解了,否则您只需要一个接口即可。 因此,只要RefA-C实现相同的属性和方法,就可以了:
public interface IRef
{
string SomeProperty {get;}
void SomeMethod();
}
然后实现RefA-C的接口:
public class RefA : IRef
{
public string SomeProperty {get;}
public void SomeMethod()
{
// Do for A
}
}
public class RefB : IRef
{
public string SomeProperty {get;}
public void SomeMethod()
{
// Do for B
}
}
然后,您可以将接口称为实现的接口:
public IRef LoadedClass;
并实例化如下:
if (UseConfigA) LoadedClass = new RefA(); // etc
如果这些类没有一个共同的祖先,并且具有不同的方法名,则可以将它们每个子类化,实现一个创建代理对象的共同接口。
interface ICommonFunctions
{
void MethodA();
void MethodB();
}
class ProxyRefA : ICommonFunctions
{
refA proxyObj = new refA;
void MethodA() { proxyObj.methodWithOtherName(); }
void MethodB() { proxyObj.otherMethodName(); }
}
/* The same for refB and refC */
等等。
通过这种方式,您可以在原始代码中拥有:
public ICommonFunctions LoadedClass;
...
编辑 :实施史蒂文·杰里斯的建议。 在代理类中使用合成代替继承。
这就是我要做的:
这就是生成的代码:
public ICommonStuff LoadedClass;
public Init()
{
/* load the object, according to which version we need... */
if (Config.Version == "refA")
{
LoadedClass = new WrapperA(new refA());
}
else if (Config.Version == "refB")
{
LoadedClass = new WrapperB(new refB());
}
else if (Config.Version == "refC")
{
LoadedClass = new WrapperC(new refC());
}
Run();
}
private void Run(){
{
LoadedClass.SomeProperty...
LoadedClass.SomeMethod(){ etc... }
}
我建议为不同的类编写一个通用适配器 。 然后,您将拥有一个通用接口,该接口可处理访问所使用的特定命名基础属性/方法。
更新:
“每个refA,refB和refC都将实现相同的属性和方法,但名称不同 。”
我解释说属性和方法的名称不同,但是现在我猜您可能仅表示refA refB和refC具有不同的名称?
如果允许您调整不同的实现 ,请为它们提供一个通用接口,并在整个代码中使用它,如其他答案所述。 否则,适配器可能仍然是可行的方法,或者您可以为每个适配器创建一个包装器类 ,并实现所需的接口。
声明共享.NET程序集中的接口。
创建从接口继承的A,B和C类,并将它们放在不同的程序集中。
在主项目中使用Assembly.Load()加载要使用的程序集。 从接口中找到该类中的类并创建实例。
我建议,如果3种不同类型共享一个公共接口,那么它们应该实现一个公共接口。 例如, IExample
然后,您可以从配置文件中加载正确的实施实例。
// public fields are a no-no, use properties instead
public IExample LoadedClass { get; private set; }
。 。 。
LoadedClass = (IExample)Activator.CreateInstance(Config.Version);
其中Config.Version
是类的全名,例如Namespace.RefA
您确实需要一个接口。 例如,考虑每个类提供一个doThis()方法,但RefA将其实现为a(),RefB将其实现为b(),而RefC将其实现为c()。 您可以将接口视为无法提供任何代码的抽象类,但是一个类可以在其中插入多个代码。
您可以按如下方式创建界面:
interface CanDoThis{
public void doThis();
}
然后,您需要按如下所示修改类文件:
public class RefA : CanDoThis // this means "I implement the interface CanDoThis"
{
// Add this method, it is needed for the interface
public void doThis(){
a();
}
public void a(){
// this has already been provided in the origional class file
}
}
对于RefB和RefC同样如此。 您的代码将变为:
public CanDoThis loadedClass;
public Init()
{
/* load the object, according to which version we need... */
if (Config.Version == "refA")
{
loadedClass = new RefA();
}
// etc
}
请注意,您将只能调用接口中定义的方法,因此需要在接口中定义要调用的每个方法。
如果您编写的程序不错,则不需要它,但是如果您想检查实例所属的类,则可以像使用子类一样使用标准的“ is”:if(loadedClass is RefA){//。 ..}
对我来说,这似乎是一个恢复工厂模式的好机会。 创建您的通用接口,将其分配给所有三个类,然后旋转正确的类。 这些都是受界面约束的,因此您不必做任何太怪异的事情。
class Program
{
static void Main(string[] args)
{
RefFactory factory = new RefFactory();
ICommonFunctionality a = factory.Create(0);
Console.WriteLine(a.SomeMethod());
ICommonFunctionality b = factory.Create(1);
Console.WriteLine(b.SomeMethod());
ICommonFunctionality c = factory.Create(2);
Console.WriteLine(c.SomeMethod());
//The above is to just test. Should be something like this:
ICommonFunctionality Ref;
if (1 == 1)
{
Ref = factory.Create(0);
}
if (1 == 2)
{
Ref = factory.Create(1);
}
//etc..
Console.Read();
}
}
public class RefFactory
{
public ICommonFunctionality Create(int someCondition)
{
if (someCondition == 0)
{
return new RefA();
}
else if (someCondition == 1)
{
return new RefB();
}
else
{
return new RefC();
}
}
}
public interface ICommonFunctionality
{
bool SomeProperty { get; set; }
string SomeMethod();
}
public class RefA : ICommonFunctionality
{
public bool SomeProperty { get; set; }
public string SomeMethod()
{
return "RefA";
}
}
public class RefB : ICommonFunctionality
{
public bool SomeProperty { get; set; }
public string SomeMethod()
{
return "RefB";
}
}
public class RefC : ICommonFunctionality
{
public bool SomeProperty { get; set; }
public string SomeMethod()
{
return "RefC";
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.