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

时间:2018-09-04 09:14:08

标签: c# generics polymorphism com-interop

我搞砸了来自两个COM组件的两个对象,但是它们基本上是相同的东西,只是使用了不同的方法,并且几乎没有什么不同(但从技术上讲它们是不同的类)

说有一个对象ab我要处理:

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

我想访问a的{​​{1}}的某些成员,但它们仍然是不同的类

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.member1a,而NamespaceA.someClassA中的typeof target.member1b,但是它们具有相同的名字(对于大多数成员)

Q:NamespaceB.someClassBDoWorkA几乎相同,是否可以为DoWorkBDoWork编写通用方法a? >


p.s。我尝试了b,但是由于Visual Studio不能告诉DoWork<T>(T target) where T:A,B正在调用target.member1someClassA

,它无法构建
  

错误someClassBmember1NamespaceA.someClassA.member1之间的模糊引用


对于任何想知道的人,他们是:

NamespaceB.someClassB .member1aAutoCAD.AcadDocumentb

并且没有使AXDBLib.AxDbDocumentIDocumenta is IDocument的类或接口b is IDocument

1 个答案:

答案 0 :(得分: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);
}

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

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

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