jlvaquero
jlvaquero

Reputation: 8785

Unity BuildUp without DependencyAttribute

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

Answers (2)

Randy Levy
Randy Levy

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

Faster Solutions
Faster Solutions

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

Related Questions