I am working with C#
, .NET 4.5
.
I have 2 objects (actually more but for sake of simplicity lets stick with two) that are separate entities and all come from 3rd party libraries, however they do have few common properties.
I want to do an abstract mechanism that would work with these properties. If these objects would be mine I could do it easily by adding 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)
}
}
However since they come from 3rd party I have no (don't know a) way of putting them behind interface.
Options I see ATM:
Convert Foo
and Bar
to MyFoo
and MyBar
that are my internal objects put MyFoo
and MyBar
behind interface and handle them this way
Use a method that accepts only properties as inputs.
Tuple<string, string> DoThings(string A, string B)
{
...(do things to A and B)
}
This will involve lots of mapping from each flavour of 3rd party object.
At this point I am leaning to using reflection.
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;
}
Is there a way to 'sneak' interface behind 3rd party objects (or some other workaround) that would allow me to make multiple objects seem as if they are behind interface, so I could deal with them all in same way.
What gives me hope that this could be done - there's PostSharp that does allows to do 'Aspect Inheritance' (haven't tried it myself, so it might be something different) in pay'd version and if they do this somehow - then this can be done.
What you need is adapter pattern.
You can create classes that implements your interface and use Foo & Bar in the background:
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; }
}
}
If you want a correct or most common solution you should follow Ufuk´s answer.
My solution provides a faster way to solve the problem, but in case of a longterm use this is not recommended.
When I understand your problem correct, you could try to use a method that accepts a dynamic object as parameter.
public static void ChangeCommonProperties(dynamic thirdPartyObject){
thirdPartyObject.A = "Hello";
thirdPartyObject.B = "World";
}
ChangeCommonProperties(new Foo());
ChangeCommonProperties(new Bar());
As long as the object passed in has the properties and the property type is correct, this works without problems. Otherwise you get a RuntimeBinderException
with details what went wrong.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With