如何潜行'第三方对象后面的界面

时间:2015-01-09 10:05:51

标签: c# interface .net-4.5

我正在使用C#.NET 4.5 我有2个对象(实际上更多但为了简单起见,我们坚持使用两个),这些对象是独立的实体,并且都来自第三方库,但它们确实具有很少的共同属性。

我想做一个可以使用这些属性的抽象机制。如果这些对象是我的,我可以通过添加接口

轻松完成
class Foo : IFooBar
{
    public string A { get; set; }
    public string B { get; set; }
}

class Bar : IFooBar
{
    public string A { get; set; }
    public string B { get; set; }
}

interface IFooBar
{
    string A { get; set; }
    string B { get; set; }
}

public static class Extensions
{
    public static IFooBar ProcessedFoobars(IFooBar fooBar)
    {
    ...(do things to A and B)
    }
}

然而,由于他们来自第三方,我没有(不知道)将它们置于界面之后的方式。

我看到ATM的选项:

  1. FooBar转换为我的内部对象的MyFooMyBar,将MyFooMyBar置于界面后面以这种方式处理它们

  2. 使用仅接受属性作为输入的方法。

    Tuple<string, string> DoThings(string A, string B)
    {
    ...(do things to A and B)
    }
    
  3. 这将涉及来自第三方对象的每种风格的大量映射。

    1. 此时我倾向于使用反射。

      public T FooBarProcessor<T>(T fooBar)
      {
          var type = typeof (T);
          var propertyA = type.GetProperty("A");
          var propertyB = type.GetProperty("B");
          var a = propertyA.GetValue(fooBar, null);
          var b = propertyB.GetValue(fooBar, null);
          ... (do things to A and B)
          propertyA.SetValue(fooBar, a);
          propertyB.SetValue(fooBar, b);
          return fooBar;
      }
      
    2. 有没有办法'隐藏'第三方对象(或其他一些解决方法)背后的界面,这样我就可以让多个对象看起来像是在界面后面,所以我可以同时处理它们方式。

      是什么让我希望能够做到这一点 - 有PostSharp确实允许做'方面继承'(我自己没有尝试过,所以可能会有所不同)版本,如果他们以某种方式这样做 - 那么这可以做到。

3 个答案:

答案 0 :(得分:8)

您需要的是adapter pattern

您可以创建实现您的界面的类并使用Foo&amp;酒吧在后台:

interface IFooBar
{
    string A { get; set; }
    string B { get; set; }
}

class FooAdapter : IFooBar
{
    private readonly Foo _foo;

    public FooAdapter(Foo foo)
    {
        _foo = foo;
    }

    public string A
    {
        get { return _foo.A; }
        set { _foo.A = value; }
    }

    public string B
    {
        get { return _foo.B; }
        set { _foo.B = value; }
    }
}


class BarAdapter : IFooBar
{
    private readonly Bar _bar;

    public BarAdapter(Bar bar)
    {
        _bar = bar;
    }

    public string A
    {
        get { return _bar.A; }
        set { _bar.A = value; }
    }

    public string B
    {
        get { return _bar.B; }
        set { _bar.B = value; }
    }
}

答案 1 :(得分:2)

如果您想要正确或最常见的解决方案,请遵循Ufuk´s answer

我的解决方案提供了一种更快的方法来解决问题,但是如果长期使用,建议不要这样做。

当我理解你的问题是正确的时,你可以尝试使用一个接受动态对象作为参数的方法。

public static void ChangeCommonProperties(dynamic thirdPartyObject){
  thirdPartyObject.A = "Hello";
  thirdPartyObject.B = "World";
}

ChangeCommonProperties(new Foo());
ChangeCommonProperties(new Bar());

只要传入的对象具有属性且属性类型正确,就可以正常工作。否则,您会收到RuntimeBinderException详细信息。

答案 2 :(得分:0)

我最终使用了稍微修改过的解决方案,感谢@Jehof。

public T ProcessFooBars<T>(dynamic anything) 
{ 
    return (T) ChangeCommonProperties(anything); 
}

public dynamic ChangeCommonProperties(dynamic thirdPartyObject)
{
    thirdPartyObject.A = "Hello";
    thirdPartyObject.B = "World";
}

希望这可以节省你一些时间。