我正在使用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的选项:
将Foo
和Bar
转换为我的内部对象的MyFoo
和MyBar
,将MyFoo
和MyBar
置于界面后面以这种方式处理它们
使用仅接受属性作为输入的方法。
Tuple<string, string> DoThings(string A, string B)
{
...(do things to A and B)
}
这将涉及来自第三方对象的每种风格的大量映射。
此时我倾向于使用反射。
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;
}
有没有办法'隐藏'第三方对象(或其他一些解决方法)背后的界面,这样我就可以让多个对象看起来像是在界面后面,所以我可以同时处理它们方式。
是什么让我希望能够做到这一点 - 有PostSharp确实允许做'方面继承'(我自己没有尝试过,所以可能会有所不同)版本,如果他们以某种方式这样做 - 那么这可以做到。
答案 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";
}
希望这可以节省你一些时间。