具有不同类型的接口的实现?

时间:2011-03-04 15:02:57

标签: c# oop class 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技能。提前感谢大家的耐心!

8 个答案:

答案 0 :(得分:4)

除非我误解,否则你只需要一个界面。因此,只要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

答案 1 :(得分:2)

如果类没有共同的祖先并且具有不同的方法名称,则可以将每个类子类化,实现创建代理对象的公共接口。

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;

...

编辑:实施Steven Jeuris建议。在代理类中使用组合而不是继承。

答案 2 :(得分:2)

这就是我要做的事情:

  1. 创建一个接口(让我们称之为ICommonStuff),它具有refA,refB和refC之间共享的所有属性和方法。
  2. 对于refA,refB和refC中的每一个,创建一个包装类,它接受类型作为参数并实现接口ICommonStuff。
  3. 主要实现您的Init方法,除了不直接将LoadedClass属性设置为refA,refB或refC,将其设置为其中一个包装器。
  4. 这就是生成的代码:

    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... }
    }
    

答案 3 :(得分:0)

我建议为不同的类写一个共同的adapter。然后,您将拥有一个通用接口来处理访问所使用的特定命名基础属性/方法。

更新:

“refA,refB和refC中的每一个都将实现相同的属性和方法,但不同的名称。”

我解释说属性和方法的名称不同,但现在我猜你可能只是说refA refB和refC有不同的名字?

如果允许调整不同的实现,请为它们提供一个通用接口,并在整个代码中使用它,如其他答案中所述。否则,适配器可能仍然是一种可行的方法,或者您可以为它们中的每一个创建包装类,并实现所需的接口。

答案 4 :(得分:0)

在共享.NET程序集中声明接口。

创建从Interface继承的A,B和C类,并将它们放在不同的程序集中。

在主项目中使用Assembly.Load()来加载您想要使用的程序集。查找其中包含接口的类并创建实例。

答案 5 :(得分:0)

我建议如果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

答案 6 :(得分:0)

你确实需要一个接口。例如,考虑每个类提供方法doThis(),但RefA将其实现为(),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是RefA){         // ...     }

答案 7 :(得分:0)

factory pattern来说,这似乎是一个很好的机会。创建您的通用界面,将其提供给所有三个类,并启动正确的类。这些都受到界面的约束,所以你真的不必做任何太奇怪的事情。

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";
        }
    }