如何重用两个类似COM对象的代码?

问题描述 投票:1回答:1

我正在搞乱来自两个COM组件的两个对象,但是它们基本上是相同的,具有不同的方法并且几乎没有(但从技术上讲它们是不同的类)

说我要处理的对象ab

var app = Marshal.GetActiveObject("MotherClassOfA&B");
NamespaceA.A a = app.OpenAsA("random-filepath") ;
NamespaceB.B b = app.OpenAsB("random-filepath") ;

我想访问一些a的成员,也可以从b获得,但是,他们仍然是不同的类

public void DoWorkA(NamespaceA.A target){
  DealWith(target.member1);
  Check(target.member2);
  BlahBlah(target.member3);
  ... // many others
}

public void DoWorkB(NamespaceB.B target){
  DealWith(target.member1); 
  Check(target.member2);
  BlahBlah(target.member3);
  ... // many others same as DoWorkA
}

虽然它们有相同的名字,typeof target.member1aNamespaceA.someClassA,而typeof target.member1bNamespaceB.someClassB,但它们有相同的名称(对于大多数成员而言)

问:DoWorkADoWorkB几乎相同,是否有可能为DoWorka写一个通用方法b


附:我尝试了DoWork<T>(T target) where T:A,B,但它无法构建,因为Visual Studio无法告诉target.member1正在调用someClassAsomeClassB

错误member1NamespaceA.someClassA.member1NamespaceB.someClassB .member1之间的模糊参考


对于任何想知道的人,具体来说,他们是:

aAutoCAD.AcadDocumentbAXDBLib.AxDbDocument

并且没有类或界面IDocument使a is IDocumentb is IDocument两个true

c# generics polymorphism com-interop
1个回答
0
投票

响应your comment并在@JeroenMostert's suggestion上构建,您可以为所有方法使用一个界面,或者为每种方法使用一个界面,或者根据您的需要使用其中任何一种方法。让我们为所有方法创建一个......

interface IDocumentAdapter
{
    bool Member1
    {
        get; set;
    }

    int Member2
    {
        get; set;
    }

    string Member3
    {
        get; set;
    }
}

对于您正在调整的每种类型,您将需要一个实现此接口的类,并包含对适应类型的实例的引用...

class AcadDocumentAdapter : IDocumentAdapter
{
    public AcadDocumentAdapter(AutoCAD.AcadDocument document)
    {
        Document = document;
    }

    private AutoCAD.AcadDocument Document
    {
        get;
    }

    public bool Member1
    {
        get => Document.Member1;
        set => Document.Member1 = value;
    }

    public int Member2
    {
        get => Document.Member2;
        set => Document.Member2 = value;
    }

    public string Member3
    {
        get => Document.Member3;
        set => Document.Member3 = value;
    }
}

class AxDbDocumentAdapter : IDocumentAdapter
{
    public AxDbDocumentAdapter(AXDBLib.AxDbDocument document)
    {
        Document = document;
    }

    private AXDBLib.AxDbDocument Document
    {
        get;
    }

    public bool Member1
    {
        get => Document.Member1;
        set => Document.Member1 = value;
    }

    public int Member2
    {
        get => Document.Member2;
        set => Document.Member2 = value;
    }

    public string Member3
    {
        get => Document.Member3;
        set => Document.Member3 = value;
    }
}

然后,您只需要一个DoWork()方法,通过IDocumentAdapter接口执行其逻辑...

public void DoWork(IDocumentAdapter documentAdapter)
{
    DealWith(documentAdapter.Member1);
    Check(documentAdapter.Member2);
    BlahBlah(documentAdapter.Member3);
}

或者,您可以简单地编写一个带有DoWork()参数的dynamic方法...

public void DoWork(dynamic target)
{
    DealWith(target.member1);
    Check(target.member2);
    BlahBlah(target.member3);
}

这样做的好处就是不必为数百个成员编写适配器代码,但是缺点是在使用dynamic变量时你不会得到任何编译器/ Intellisense帮助,因为成员访问不会被评估/检查/绑定直到运行。

© www.soinside.com 2019 - 2024. All rights reserved.