Reputation: 8785
I've got a third party library returning a class instace. It's out of my cotrol but I want to use Unity
to inyect in its public properties. As I can not add DependecyAttribute
to its properties because the class is not partial nor inheritalbe, I wondering if I can use Unity
XML configuration to do the inyection.
Is it possible to use Unity's
XML configuration to configure build up dependencies? If answer is yes. How to configure XML to do it?
I've tried:
<register type="IService" mapTo="Service"> <!--Service has public constructor-->
</register>
<!--ThirdPartyObj has no interface and no public constructor-->
<register type="ThirdPartyObj " mapTo="ThirdPartyObj">
<!-- Inject the property "Service" -->
<property name="Service" /> //type of the property is IService
</register>
This config will work if Unity Resolve
ThidPartyObj
buy not working in BuilUp
(Null reference in Service property) and can not Resolve
ThirdPartyObj
because has no public constructor.
Simple example of what I want to archieve:
IUnityContainer uc = New UnityContainer() //create container
container.LoadConfiguration() // load from XML config
ThirdPartyObj foo = ThirdPartyLibrary.getFooInstace() //get third party instance
container.BuildUp(foo.getType, foo) //inyect dependencies
Console.WriteLine(foo.Service.getServiceMessage)
Upvotes: 0
Views: 337
Reputation: 22655
Based on your posted code, there shouldn't be a problem.
I created 2 projects: a console application and a class library called ThirdPartyLibrary.
The ThirdPartyLibrary consists of the following (extrapolated from the posted code):
namespace ThirdPartyLibrary
{
public interface IService
{
string GetServiceMessage { get; }
}
public class Service : IService
{
public Service() { }
public string GetServiceMessage
{
get { return "The message!"; }
}
}
public static class ThirdPartyLibrary
{
public static ThirdPartyObj GetFooInstance()
{
return new ThirdPartyObj();
}
}
public interface IThirdPartyObj { }
public class ThirdPartyObj : IThirdPartyObj
{
internal ThirdPartyObj() { }
public IService Service { get; set; }
}
}
The XML Configuration looks like this:
<?xml version="1.0"?>
<configuration>
<configSections>
<section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration"/>
</configSections>
<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
<container>
<register type="ThirdPartyLibrary.IService, ThirdPartyLibrary" mapTo="ThirdPartyLibrary.Service, ThirdPartyLibrary">
</register>
<register type="ThirdPartyLibrary.IThirdPartyObj, ThirdPartyLibrary" mapTo="ThirdPartyLibrary.ThirdPartyObj, ThirdPartyLibrary">
<!-- Inject the property "Service" -->
<property name="Service" />
</register>
</container>
</unity>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5"/>
</startup>
</configuration>
And the console application is:
class Program
{
static void Main(string[] args)
{
IUnityContainer container = new UnityContainer(); //create container
container.LoadConfiguration(); // load from XML config
ThirdPartyObj foo = ThirdPartyLibrary.ThirdPartyLibrary.GetFooInstance(); //get third party instance
container.BuildUp(foo.GetType(), foo); //inyect dependencies
Console.WriteLine(foo.Service.GetServiceMessage);
}
}
This works fine and outputs The message!
as expected. Perhaps, the exact scenario is not the same as your posted (I assume fictitious) example or something else is not configured properly?
Upvotes: 1
Reputation: 7005
Create a wrapper for this that is Unity-friendly:
public interface IThirdpartyWrapper
{
ThirdpartyObj ConfiguredObject{get;}
}
public class ThirdpartyWrapper:IThirdpartyWrapper
{
private ThirdpartyObject _thirdPartyObject;
public ThirdpartyWrapper(IService myService)
{
_thirdPartyObject=ThirdPartyLibrary.getFooInstance();
_thirdPartyObject.Service=myService;
}
public ThirdpartyObj ConfiguredObject
{
get{return _thirdPartyObject;}
}
}
Now we have a Unity-friendly class to play with
Unity Xml Config:
<register type="IService" mapTo="Service"> <!--Service has public constructor-->
</register>
<!--ThirdPartyObj has no interface and no public constructor-->
<register type="IThirdpartyWrapper" mapTo="IThirdpartyWrapper">
</register>
When I do the following:
var wrapper=_container.Resolve<IThirdpartyWrapper>();
var configuredObject=wrapper.ConfiguredObject;
The wrapper instantiates a copy of the thirdparty object and then injects the service into the appropriate property (or could be passed in via a method call, etc).
This won't take much code, is unit-testable and does what you need.
Upvotes: 1