如何 'sneak' 接口在第 3 方对象后面
How to 'sneak' interface behind 3rd party objects
我正在与 C#
、.NET 4.5
合作。
我有 2 个对象(实际上更多,但为了简单起见,让我们坚持使用两个),它们是独立的实体,并且都来自第三方库,但是它们确实没有什么共同的属性。
我想做一个可以处理这些属性的抽象机制。如果这些对象是我的,我可以通过添加 interface
轻松完成
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)
}
}
然而,由于它们来自第 3 方,我没有(不知道)将它们放在界面后面的方法。
我看到 ATM 的选项:
将 Foo
和 Bar
转换为我的内部对象 MyFoo
和 MyBar
放置 MyFoo
和 MyBar
在界面后面并以这种方式处理它们
使用仅接受属性作为输入的方法。
Tuple<string, string> DoThings(string A, string B)
{
...(do things to A and B)
}
这将涉及来自各种类型的第 3 方对象的大量映射。
目前我倾向于使用反射
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;
}
有没有办法 'sneak' 在第 3 方对象后面进行接口(或其他一些解决方法),让我可以让多个对象看起来好像在接口后面,所以我可以以同样的方式处理它们。
是什么让我希望可以做到这一点 - PostSharp 确实允许 'Aspect Inheritance'(我自己没有尝试过,所以可能有所不同) 在付费版本中,如果他们以某种方式这样做 - 那么就可以做到。
你需要的是adapter pattern.
您可以创建 类 实现您的界面并在后台使用 Foo & Bar:
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; }
}
}
如果您想要正确或最常见的解决方案,您应该遵循 。
我的解决方案提供了一种更快的解决问题的方法,但如果要长期使用,则不建议这样做。
当我理解你的问题正确时,你可以尝试使用接受动态对象作为参数的方法。
public static void ChangeCommonProperties(dynamic thirdPartyObject){
thirdPartyObject.A = "Hello";
thirdPartyObject.B = "World";
}
ChangeCommonProperties(new Foo());
ChangeCommonProperties(new Bar());
只要传入的对象具有属性并且 属性 类型正确,这就没有问题。否则你会得到一个 RuntimeBinderException
详细说明出了什么问题。
感谢@Jehof,我最终使用了略微修改的解决方案。
public T ProcessFooBars<T>(dynamic anything)
{
return (T) ChangeCommonProperties(anything);
}
public dynamic ChangeCommonProperties(dynamic thirdPartyObject)
{
thirdPartyObject.A = "Hello";
thirdPartyObject.B = "World";
}
希望这能为您节省一些时间。
我正在与 C#
、.NET 4.5
合作。
我有 2 个对象(实际上更多,但为了简单起见,让我们坚持使用两个),它们是独立的实体,并且都来自第三方库,但是它们确实没有什么共同的属性。
我想做一个可以处理这些属性的抽象机制。如果这些对象是我的,我可以通过添加 interface
轻松完成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)
}
}
然而,由于它们来自第 3 方,我没有(不知道)将它们放在界面后面的方法。
我看到 ATM 的选项:
将
Foo
和Bar
转换为我的内部对象MyFoo
和MyBar
放置MyFoo
和MyBar
在界面后面并以这种方式处理它们使用仅接受属性作为输入的方法。
Tuple<string, string> DoThings(string A, string B) { ...(do things to A and B) }
这将涉及来自各种类型的第 3 方对象的大量映射。
目前我倾向于使用反射
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; }
有没有办法 'sneak' 在第 3 方对象后面进行接口(或其他一些解决方法),让我可以让多个对象看起来好像在接口后面,所以我可以以同样的方式处理它们。
是什么让我希望可以做到这一点 - PostSharp 确实允许 'Aspect Inheritance'(我自己没有尝试过,所以可能有所不同) 在付费版本中,如果他们以某种方式这样做 - 那么就可以做到。
你需要的是adapter pattern.
您可以创建 类 实现您的界面并在后台使用 Foo & Bar:
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; }
}
}
如果您想要正确或最常见的解决方案,您应该遵循
我的解决方案提供了一种更快的解决问题的方法,但如果要长期使用,则不建议这样做。
当我理解你的问题正确时,你可以尝试使用接受动态对象作为参数的方法。
public static void ChangeCommonProperties(dynamic thirdPartyObject){
thirdPartyObject.A = "Hello";
thirdPartyObject.B = "World";
}
ChangeCommonProperties(new Foo());
ChangeCommonProperties(new Bar());
只要传入的对象具有属性并且 属性 类型正确,这就没有问题。否则你会得到一个 RuntimeBinderException
详细说明出了什么问题。
感谢@Jehof,我最终使用了略微修改的解决方案。
public T ProcessFooBars<T>(dynamic anything)
{
return (T) ChangeCommonProperties(anything);
}
public dynamic ChangeCommonProperties(dynamic thirdPartyObject)
{
thirdPartyObject.A = "Hello";
thirdPartyObject.B = "World";
}
希望这能为您节省一些时间。