My code is as follows
IUnityContainer container = new UnityContainer();
container
.ConfigureAutoRegistration()
.LoadAssemblyFrom(typeof(Test).Assembly.Location)
.LoadAssemblyFrom(typeof(ITest).Assembly.Location)
.ApplyAutoRegistration();
This is my first question.
I'm not sure whether I have used the LoadAssemblyFrom method correctly here:
ITest test = container.Resolve<ITest>();
When I try to compile I get the exception "ResolutionFailedException".
What am I doing wrong?
Thanks for your time in advance.
It appears that what you are looking for is this:
container.ConfigureAutoRegistration()
.LoadAssemblyFrom(typeof(ITest).Assembly.Location)
.LoadAssemblyFrom(typeof(Test).Assembly.Location)
.Include(If.ImplementsITypeName, Then.Register())
.ApplyAutoRegistration();
This will tell Unity.AutoRegistration to register all types where there is an interface with the same name, prefixed with I.
Here is a complete working console example showing how to set Unity up for registration by convention, then transfer control into the dependency injection world. You will have to add the Unity NuGet package for this to work.
Tested with Unity v3.5 and VS 2012.
#region
using System;
using Microsoft.Practices.Unity;
#endregion
namespace Demo___Unity
{
internal class Program
{
private static void Main(string[] args)
{
using (var container = new UnityContainer())
{
// Manual method.
//container.RegisterType<IEntryPoint, EntryPoint>();
//container.RegisterType<IInjected, Injected>();
// Set up registration by convention.
// http://blogs.msdn.com/b/agile/archive/2013/03/12/unity-configuration-registration-by-convention.aspx
container.RegisterTypes(
AllClasses.FromAssembliesInBasePath(),
WithMappings.FromMatchingInterface,
WithName.Default,
WithLifetime.ContainerControlled);
var controller = container.Resolve<IEntryPoint>();
controller.Main();
}
}
}
public interface IEntryPoint
{
string Name { get; set; }
void Main();
}
public class EntryPoint : IEntryPoint
{
private readonly IInjected Injected;
public EntryPoint(IInjected injected)
{
Injected = injected;
}
public void Main()
{
Console.Write("Hello, world!\n");
Injected.SubMain();
Injected2.SubMain();
Console.Write("[any key to continue]");
Console.ReadKey();
}
// Demonstrates property injection.
[Dependency]
public IInjected Injected2 { get; set; }
public string Name { get; set; }
}
public interface IInjected
{
void SubMain();
}
public class Injected : IInjected
{
public void SubMain()
{
Console.Write("Hello, sub world!\n");
}
public string Name { get; set; }
}
}
Related
The below code does what I would like it to do. The code in the Main method looks and behaves exactly as desired. However, it would be preferable if the class UserMenu, Home and DropdownMenu2 could only be used by the HeaderNavigationMenu to protect other developers from trying to used them outside of the HeaderNavigationMenu class. Additionally most articles frown upon making everything public.
Question:
Is the design patter being used below appropriate or is there something better and more acceptable to use in this scenario?
Edit: The reason for this design.
I wanted the end user of HeaderNavigationMenu to just be able to use the dot notation to get a list of available options. This Architecture accomplishes this goal (ex: navigationMenu.DropdownMenu2.SelectOption3())
Wanted anyone else who eventually might need to edit the code to understand that the classes UserMenu, Home and DropDownMenu2 where very specifically designed to be implemented by HeaderNavigationMenu class.
public class HeaderNavigationMenu
{
public HeaderNavigationMenu()
{
UsersMenu = new UsersMenu();
Home = new Home();
DropdownMenu2 = new DropdownMenu2();
}
public UsersMenu UsersMenu { get; set; }
public Home Home { get; set; }
public DropdownMenu2 DropdownMenu2 { get; set; }
}
public class UsersMenu
{
...
}
public class Home
{
...
}
public class DropdownMenu2
{
public void SelectOption3()
{
...
}
...
}
static void Main(string[] args)
{
HeaderNavigationMenu navigationMenu = new HeaderNavigationMenu();
navigationMenu.DropdownMenu2.SelectOption3();
// The following code is an example of undesired capability;
// prefer if Home class could only be
// used by HeaderNavigationMenu class
Home home = new Home();
}
Restrict access to the class constructors. If they are declared as "internal" then the classes may only be created by your code.
If you're looking to protect against the instantiation of UsersMenu, DropdownMenu2, and Home from outside HeaderNavigationMenu but still within the same project as HeaderNavigationMenu then there is a neat trick that can achieve this behavior. You can use public nested classes with private constructors which statically initialize their own factory methods. The basic template for this would be:
public class Outer{
private static Func<Inner> _innerFactory;
public Inner ExposedInner {get; private set;}
public Outer(){
// Force the static initializer to run.
System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(typeof(Inner).TypeHandle);
// Call the newly created factory method instead of a regular constructor.
ExposedInner = _innerFactory();
}
public class Inner {
static Inner(){
// Initialize Outer's static factory method.
_innerFactory = () => new Inner();
}
// Inner cannot be instantiated (without reflection) because its constructor is private.
private Inner(){}
// This method is now exposed for anyone to use.
public void DoStuff(){ Console.WriteLine("Did stuff"); }
}
}
Here's this concept implemented in your example:
class Program
{
static void Main(string[] args)
{
HeaderNavigationMenu navigationMenu = new HeaderNavigationMenu();
navigationMenu.DropdownMenu2.SelectOption3();
// This line will no longer work because the constructors
// for the inner classes are private.
HeaderNavigationMenu.HomeImpl home = new HeaderNavigationMenu.HomeImpl();
Console.ReadKey();
}
}
public class HeaderNavigationMenu
{
//Private factory methods that are statically initialized
private static Func<UsersMenuImpl> _createUsers;
private static Func<DropdownMenu2Impl> _createDropdown;
private static Func<HomeImpl> _createHome;
public HeaderNavigationMenu()
{
//Force the static constructors to run
System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(typeof(UsersMenuImpl).TypeHandle);
System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(typeof(HomeImpl).TypeHandle);
System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(typeof(DropdownMenu2Impl).TypeHandle);
UsersMenu = _createUsers();
Home = _createHome();
DropdownMenu2 = _createDropdown();
}
public UsersMenuImpl UsersMenu { get; set; }
public HomeImpl Home { get; set; }
public DropdownMenu2Impl DropdownMenu2 { get; set; }
public class UsersMenuImpl
{
//Static constructor to make the class factory method
static UsersMenuImpl()
{
_createUsers = () => new UsersMenuImpl();
}
private UsersMenuImpl() { }
}
public class HomeImpl
{
//Static constructor to make the class factory method
static HomeImpl()
{
_createHome = () => new HomeImpl();
}
private HomeImpl() { }
}
public class DropdownMenu2Impl
{
//Static constructor to make the class factory method
static DropdownMenu2Impl()
{
_createDropdown = () => new DropdownMenu2Impl();
}
private DropdownMenu2Impl() { }
public void SelectOption3()
{
}
}
}
With this, you will still be able to use all the public properties of the inner classes however no one will be able to instantiate the inner classes from outside HeaderNavigationMenu and only HeaderNavigationMenu has access to the factory methods.
I don't really understand what your use case is and I've never coded like this but one way of only exposing the required behaviour of HeaderNavigationMenu would be to make the classes internal and the variables private and then expose only the SelectOption3() method, as below.
If you uncomment the line
//Home home = new Home();
you will get a compiler error.
class Program
{
static void Main(string[] args)
{
HeaderNavigationMenu navigationMenu = new HeaderNavigationMenu();
navigationMenu.DropdownMenu2SelectOption3();
// The following code is an example of undesired capability;
// prefer if Home class could only be
// used by HeaderNavigationMenu class
//Home home = new Home();
}
}
public class HeaderNavigationMenu
{
UsersMenu usersMenu;
Home home;
DropdownMenu2 dropdownMenu2;
public HeaderNavigationMenu()
{
usersMenu = new UsersMenu();
home = new Home();
dropdownMenu2 = new DropdownMenu2();
}
public void DropdownMenu2SelectOption3()
{
dropdownMenu2.SelectOption3();
}
class UsersMenu
{
}
class Home
{
}
class DropdownMenu2
{
public void SelectOption3()
{
}
}
}
You could make UsersMenu, Home, and DropdownMenu2 public abstract classes. Then have private classes nested inside of HeaderNavigationMenu which extend the public abstract versions.
public abstract class UsersMenu
{
}
public abstract class Home
{
}
public abstract class DropdownMenu2
{
public void SelectOption3()
{
// Code for SelectOption3...
}
}
public class HeaderNavigationMenu
{
public HeaderNavigationMenu()
{
UsersMenu = new UsersMenuImpl();
Home = new HomeImpl();
DropdownMenu2 = new DropdownMenu2Impl();
}
public UsersMenu UsersMenu { get; }
public Home Home { get; }
public DropdownMenu2 DropdownMenu2 { get; }
private class UsersMenuImpl : UsersMenu
{
}
private class HomeImpl : Home
{
}
private class DropdownMenu2Impl : DropdownMenu2
{
}
}
Fellow developers can see and use the UsersMenu, Home, and DropdownMenu2 abstract classes, but cannot create instances of them. Only HeaderNavigationMenu can.
Of course, another developer could always create their own classes deriving from the public abstract ones, but there is only so much you can do. UsersMenu, Home, and DropdownMenu2 have to be public in order to be public properties.
In Unity, I can register a named type like this
using Microsoft.Practices.Unity;
var container = new UnityContainer();
container.RegisterType<IOutputService, ConsoleOutputService>("Console");
container.RegisterType<IOutputService, MessageBoxOutputService>("MessageBox");
container.RegisterType<ICalculatorReplLoop, CalculatorReplLoop>();
ICalculatorReplLoop loop = container.Resolve<ICalculatorReplLoop>();
and auto resolve it using attribute like this
public class CalculatorReplLoop : ICalculatorReplLoop
{
public CalculatorReplLoop() {}
[Dependency("MessageBox")]
public IOutputService OutputService { get; set; }
}
I know how to register Named Service in Autofac
using Autofac;
using Autofac.Core;
var builder = new ContainerBuilder();
builder.RegisterType<ConsoleOutputService>().Named<IOutputService>("Console");
builder.RegisterType<MessageBoxOutputService>().Named<IOutputService>("MessageBox");
builder.RegisterType<CalculatorReplLoop>().As<ICalculatorReplLoop>().SingleInstance();
IContainer container = builder.Build();
ICalculatorReplLoop loop = container.Resolve<ICalculatorReplLoop>();
but how to resolve it inside CalculatorReplLoop class ?
Look at this Sample code and this is one of the ways of auto resolve the using autofac when you share a contract with two implementations.
using System;
using Autofac;
using Autofac.Features.Indexed;
namespace AutoFac
{
class Program
{
static void Main(string[] args)
{
var builder = new ContainerBuilder();
builder.RegisterType<OnlineState>().Keyed<IDeviceState>("online");
builder.RegisterType<OfflineState>().Keyed<IDeviceState>("offline");
builder.RegisterType<Modem>().AsImplementedInterfaces();
var container = builder.Build();
var r = container.Resolve<IModem>();
r.print();
}
}
public interface IDeviceState
{
string Get();
}
public class OnlineState : IDeviceState
{
public string Get()
{
return "OnlineState";
}
}
public class OfflineState : IDeviceState
{
public string Get()
{
return "OfflineState";
}
}
public class Modem : IModem
{
readonly IIndex<string, IDeviceState> _states;
private readonly IDeviceState _deviceState;
public Modem(IIndex<string, IDeviceState> states)
{
_states = states;
_deviceState = _states["online"];
//_deviceState = _states["offline"];
}
public void print()
{
Console.WriteLine(_deviceState.Get());
}
}
public interface IModem
{
void print();
}
}
I spent a few hours trying to resolve this but with no luck. I'm using unity to inject my _translation property in my SSPResourceManagerWrapper Class which is returning back a null, instead of the translationService object.
Registering Dependency UIbootstrapper class gets called when the app starts to register all dependencies. And resolved when controller object is created.
public class UiBootstrapper
{
public static IUnityContainer RegisterUiComponents(IUnityContainer container)
{
container.RegisterType<SSPResourceManagerWrapper>();
container.RegisterType<SSPResourceManager>();
container.RegisterType<ITranslationService, TranslationService>();
return container;
}
_translation property returning null here. instead of translationService object
public class SSPResourceManager
{
private static ITranslationService _translationService;
private static string _languageCode =
System.Web.HttpContext.Current.Session["LanguageCode"].ToString();
// constructor injection
public SSPResourceManager(ITranslationService translationService)
{
_translationService = translationService;
}
public static string SSP_Validation_Required
{
get
{
return _translationService.Read("SSP_Validation_Required", "SSP", _languageCode);
}
}
}
Where SSPResourceManager is used
public abstract class AddressVM
{
[Required(ErrorMessageResourceType = typeof(SSPResourceManager), ErrorMessageResourceName
= "SSP_Validation_Required")]
[StringLength(50)]
public string Name { get; set; }
}
You are creating your own instance of SSPResourceManagerWrapper instead of resolving it using the Unity container:
private static ITranslationService _translationService =
new SSPResourceManagerWrapper()._translation;
The container never has the opportunity to supply the dependencies. Try using Resolve:
private static ITranslationService _translationService =
container.Resolve<SSPResourceManagerWrapper>()._translation;
or even better:
private static ITranslationService _translationService =
container.Resolve<ITranslationService>();
I have a problem like this:
public interface IBaseVMFactory
{
public BaseVm Create(TransientDependency otherVM);
}
public class BaseVM
{
BaseVM(ChildVM1 child1, ChildVM2 child2)
}
public class ChildVM1
{
ChildVM1(TransientDependency otherVM)
}
All my viewModels (..VM) needs to be transient. And I need for the childVM1 to get the same instance of otherVM as given to the factory.
I tried to register the BaseVm as ScopedLifestyle, and manually implementing the factory and passing the instance when resolving inside the scope.
But still I get a new instance of the otherVM when resolving.
Am I missing something obvious here?
Kjetil.
I tried reproducing your problem with Windsor 3.2 with the code below:
using System.Diagnostics;
using Castle.Facilities.TypedFactory;
using Castle.MicroKernel.Registration;
using Castle.Windsor;
namespace ConsoleApplication2
{
public class SomeViewModel
{
public SomeViewModel(ISomeFactory factory)
{
var dependency1 = factory.CreateSomeDependency();
var dependency2 = factory.CreateSomeDependency();
Debug.Assert(dependency1 != dependency2);
Debug.Assert(dependency1.Dep == dependency2.Dep);
}
}
public class SomeDependency
{
private readonly DepDep _dep;
public SomeDependency(DepDep dep)
{
_dep = dep;
}
public DepDep Dep
{
get { return _dep; }
}
}
public class DepDep
{
}
public interface ISomeFactory
{
SomeDependency CreateSomeDependency();
}
class Program
{
static void Main(string[] args)
{
var container = new WindsorContainer();
container.AddFacility<TypedFactoryFacility>();
container.Register(
Component.For<SomeViewModel>().LifestyleTransient(),
Component.For<SomeDependency>().LifestyleTransient(),
Component.For<DepDep>().LifestyleBoundTo<SomeViewModel>(),
Component.For<ISomeFactory>().AsFactory().LifestyleTransient()
);
container.Resolve<SomeViewModel>();
}
}
}
To my suprise this just works. So it seems that the factory is now taking over the scope of the context in which it is created. I hope this will help you.
Kind regards,
Marwijn.
My previous post contains attempt use attribute-free (convention based) approach to configure MEF: MEF 2: import many.
But it contains export metadata attribute usage in the class PluginMetadataAttribute needed for lazy initialization plugin by condition (specific name, version).
How to get rid of ExportAttribute dependency?
I found three solution.
Solution 1 (using class constant fields, poor solution):
public class Plugin1 : IPlugin
{
public const string Name = "Plugin1";
public const string Version = "1.0.0.0";
public void Run()
{
Console.WriteLine("Plugin1 runed");
}
}
// ...
var builder = new RegistrationBuilder();
builder
.ForTypesDerivedFrom<IPlugin>()
.Export<IPlugin>(exportBuilder => {
exportBuilder.AddMetadata("Name", t => t.GetField("Name").GetRawConstantValue());
exportBuilder.AddMetadata("Version", t => t.GetField("Version").GetRawConstantValue());
});
Solution 2 (using class properties, poor solution):
public interface IPluginMetadata
{
string Name { get; }
string Version { get; }
}
public interface IPlugin : IPluginMetadata
{
void Run();
}
public class Plugin1 : IPlugin
{
public string Name { get { return "Plugin 1"; } }
public string Version { get { return "1.0.0.0"; } }
public void Run()
{
Console.WriteLine("Plugin1 runed");
}
}
And get properties values by method described this: https://stackoverflow.com/a/11162876/1986524
Solution 3 (using attributes, better but not all happy):
using System;
using System.ComponentModel.Composition.Hosting;
using System.ComponentModel.Composition.Registration;
using System.Reflection;
namespace MEF2
{
public interface IPluginMetadata
{
string Name { get; }
string Version { get; }
}
public interface IPlugin
{
void Run();
}
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public class PluginMetadataAttribute : Attribute, IPluginMetadata
{
public string Name { get; set; }
public string Version { get; set; }
public PluginMetadataAttribute(string name, string version)
{
Name = name;
Version = version;
}
}
[PluginMetadata("Plugin1", "1.0.0.0")]
public class Plugin1 : IPlugin
{
public void Run()
{
Console.WriteLine("Plugin1 runed");
}
}
[PluginMetadata("Plugin2", "2.0.0.0")]
public class Plugin2 : IPlugin
{
public void Run()
{
Console.WriteLine("Plugin2 runed");
}
}
class Program
{
static void Main(string[] args)
{
var builder = new RegistrationBuilder();
builder
.ForTypesDerivedFrom<IPlugin>()
.Export<IPlugin>(exportBuilder => {
exportBuilder.AddMetadata("Name", t => t.GetCustomAttribute<PluginMetadataAttribute>().Name);
exportBuilder.AddMetadata("Version", t => t.GetCustomAttribute<PluginMetadataAttribute>().Version);
});
var catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly(), builder);
using (var container = new CompositionContainer(catalog, CompositionOptions.DisableSilentRejection)) {
var plugins = container.GetExports<IPlugin, IPluginMetadata>();
foreach (var plugin in plugins) {
Console.WriteLine("{0}, {1}", plugin.Metadata.Name, plugin.Metadata.Version);
plugin.Value.Run();
}
}
}
}
}
Solution 3 contains problem in this code:
.Export<IPlugin>(exportBuilder => {
exportBuilder.AddMetadata("Name", t => t.GetCustomAttribute<PluginMetadataAttribute>().Name);
exportBuilder.AddMetadata("Version", t => t.GetCustomAttribute<PluginMetadataAttribute>().Version);
})
Problems:
Can't cancel add metadata in case of missing metadata
Duplicate code t.GetCustomAttribute<PluginMetadataAttribute>()
Export<> don't provided filter
If anyone knows of other solutions please write.
The An Attribute-Free Approach to Configuring MEF article that you reference in your other question includes an example on how to add metadata without using an attribute.
The example shows a use of the PartBuilder.ExportProperties overload that takes an Action<PropertyInfo, ExportBuilder> as a parameter and use one of the ExportBuilder.AddMetadata overloads to add metadata for the specific export.
This is not the only way to add metadata. All export methods of PartBuilder have an overload that take an Action<> (or an Action<,>) with an ExportBuilder param. You can use these overloads and add your metadata in a similar way.