Как повторно использовать код для двух похожих объектов COM? - PullRequest
0 голосов
/ 04 сентября 2018

Я возиться с двумя объектами из двух COM-компонентов, однако они в основном одно и то же с другим подходом и немногими разными (но технически это разные классы)

Скажем, есть объект a и b Я собираюсь разобраться с:

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.member1 из a - это NamespaceA.someClassA, в то время как typeof target.member1 из b - NamespaceB.someClassB, но у них одинаковое имя (для большинства членов)

Q: DoWorkA и DoWorkB почти одинаковы, можно ли написать универсальный метод DoWork для a и b?


p.s. Я попытался DoWork<T>(T target) where T:A,B, но его не удалось собрать, поскольку Visual Studio не может сказать, target.member1 вызывает someClassA или someClassB

Ошибка member1 является неоднозначной ссылкой между NamespaceA.someClassA.member1 и NamespaceB.someClassB .member1


Для тех, кто интересуется, в частности, они:

a - AutoCAD.AcadDocument, b - AXDBLib.AxDbDocument

И нет класса или интерфейса IDocument, который делает a is IDocument и b is IDocument обоими true

1 Ответ

0 голосов
/ 07 сентября 2018

Отвечая на ваш комментарий и основываясь на предложении @ JeroenMostert , вы можете использовать один интерфейс для всех методов, или один для каждого метода, или что-то среднее между ними, как считаете нужным. Давайте создадим один для всех методов ...

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

Преимущество этого заключается в том, что вам не нужно писать код адаптера для, как вы говорите, сотен членов, однако недостатком является то, что вы не будете получать никакой помощи компилятора / Intellisense при использовании переменных dynamic, поскольку доступ к элементам не оценивается / проверено / связано до времени выполнения.

...