I've got a simple object into which I'm trying to inject properties. I'm unclear why this doesn't seem to be working. My properties end up being null after I call resolve.
This is my object:
public interface IBasePage
{
[Dependency]
string Title { get; set; }
[Dependency]
string BaseUrl { get; set; }
}
This is what's in my unity config file:
<register type="IWebActionDriver" mapTo="ConcreteWebDriver"/>
<register type="IBasePage" name="LoginPage" mapTo="LoginPage">
<property name="Title" value="Login Page Title"/>
<property name="BaseUrl" value="http://dev1.company.com"/>
</register>
In the startup method for my unit tests, here's what I'm trying to do:
_container = new UnityContainer();
UnityConfigurationSection configSection =
(UnityConfigurationSection) ConfigurationManager.GetSection("unity");
configSection.Configure(_container, "testContainer");
_page = _container.Resolve<LoginPage>();
My concrete class looks like this:
[InjectionConstructor]
public LoginPage(IWebActionDriver driver)
{
_driver = driver;
_driver.Initialize();
this.CurrentPage = _driver;
}
Lo and Behold, the properties for Title and BaseUrl are null. Is it okay to use both an constructor injection and set properties on the object? Am I doing something else odd here?
The LoginPage is registered as a named registration (which makes sense because you can obviously have more than one IBasePage concrete type). So you should be able to achieve the behavior you want by resolving IBasePage by the name:
_page = _container.Resolve<IBasePage>("LoginPage");
You need to include the namespace and assembly names in the config file like:
<namespace name="MyNameSpace" />
<assembly name="MyAssemblyName" />
Related
Hopefully this is not a duplicate!
I am using Autofac.
I am struggling to inject some services with in my custom attribute called XNameDisplayFormatAttribute which inherits from DisplayFormatAttribute. The idea is that I want to get some data from database relating to current culture info for logged in user. For that I created a SettingsService but the problem is that I can not inject it in XNameDisplayFormatAttribute. I read there is not way how to inject services in attributes(not filters) but there are workarounds for that(Not quite sure how!). My custom attribute will look like this:
[AttributeUsage(AttributeTargets.Property, AllowMultiple = true)]
public class XNameDisplayFormatAttribute : DisplayFormatAttribute
{
public ISettingsService SettingsService {get;set;}
public XNameDisplayFormatAttribute (bool applyFormatInEditMode = true)
{
DataFormatString = SettingsService.GetDataFromDb();"*My format retrieved from db*";
ApplyFormatInEditMode = applyFormatInEditMode;
}
}
This is not working normally but I need something similar to this logic in order to perform get action from database.
Does anybody have any idea how this can be achievable ?
A good idea is not messing around with filters if possible, I want to keep the code clear with only appropriate attributes.
EDIT
I have used the code below as well but I get null value only in attributes:
ISettingsService settings = DependencyResolver.Current.GetService<ISettingsService>();
Here is my configuration section:
public void Configuration(IAppBuilder app)
{
var builder = new ContainerBuilder();
RegisterStartUp.RegisterDependecies(builder, app);
builder.RegisterControllers(Assembly.GetExecutingAssembly());
//Registering model binders
builder.RegisterModelBinders(Assembly.GetExecutingAssembly());
builder.RegisterModelBinderProvider();
//builder.RegisterSource(new ViewRegistrationSource());
builder.RegisterFilterProvider();
// BUILD THE CONTAINER
var container = builder.Build();
// REPLACE THE MVC DEPENDENCY RESOLVER WITH AUTOFAC
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
// REGISTER WITH OWIN
app.UseAutofacMiddleware(container);
app.UseAutofacMvc();
ConfigureAuth(app);
app.MapSignalR();
}
I think your design has some flaws.
You are using an attribute to implement business logic, but an attribute should normally contain only metadata, and for a good reason: the attribute is embedded into the assembly in a peculiar way, and processed differently from the rest of the classes.
The root problem of your idea is that an attribute is really meant to store (and eventually operate) on data known at compile time. An attribute is not (and, AFAICT, will never be) instantiated like the rest of the classes, so deendency injection does not apply.
What I would try: implement a class DisplayFormatManager and register it via Autofac as a singleton. This class is responsible for calling on the SettingsService and retrieving what you need.
On application startup, right after Autofac setup, you inject the DisplayFormatManager onto a static property of the XNameDisplayFormatAttribute class. Then hope for the best: I don't know WHEN the attribute value is going to be used.
I would search for a different path, however: if the configuration is dynamic, it should be handled via code, not via metadata, IMO. Your mileage may vary, a lot.
[AttributeUsage(AttributeTargets.Property, AllowMultiple = true)]
public class XNameDisplayFormatAttribute : DisplayFormatAttribute
{
public static DisplayFormatManager FormatsManager { get; set; }
public XNameDisplayFormatAttribute(bool applyFormatInEditMode = true)
{
DataFormatString = FormatsManager.GetDataFromDb(_dataFormatString);
ApplyFormatInEditMode = applyFormatInEditMode;
}
private string _dataFormatString;
public new string DataFormatString
{
get => FormatsManager.GetDataFromDb(_dataFormatString);
set => _dataFormatString = value;
}
}
public class DisplayFormatManager
{
public DisplayFormatManager(Func<ISettingsService> settingsServiceFactory)
{
SettingsServiceFactory = settingsServiceFactory;
}
public Func<ISettingsService> SettingsServiceFactory { get; }
public string GetDataFromDb(string format)
{
var service = SettingsServiceFactory();
return service.GetDataFromDb(format);
}
}
public interface ISettingsService
{
string GetDataFromDb(string format);
}
You could inject service into an action filter
http://docs.autofac.org/en/latest/integration/mvc.html#enable-property-injection-for-action-filters
I'm an intern at a company, and my assignment is to provide them with a working web portal. Since I'm an intern my skillset isn't that advanced yet, so they hired a senior developer that's gonna work with us. He set up our project structure etc... He told us to work with AutoFac for DI but I'm not familiar at all with this. This guy is on vacation now so he can't really help us atm.
When using Autofac I get this error and I don't know how to fix it..
The type 'projectnamespace.Repositories.IRepository' could not be
found. It may require assembly qualification, e.g. "MyType,
MyAssembly".
My Global.asax.cs
var builder = new ContainerBuilder();
//register types from configuration
builder.RegisterModule(new ConfigurationSettingsReader());
// Register your MVC controllers.
builder.RegisterControllers(Assembly.GetExecutingAssembly());
// Set the dependency resolver to be Autofac.
var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
Web.config
<autofac>
<components>
<component
type="projectnamespace.Repositories.OrderRepository, projectnamespace"
service="projectnamespace.Repositories.IRepository" />
</components>
</autofac>
IRepository.cs
public interface IRepository
{
string FetchAll();
}
OrderRepository.cs
public class OrderRepository : IRepository
{
public string FetchAll()
{
return "return something";
}
}
and last but not least HomeController
private readonly IRepository _repository;
public HomeController(OrderRepository repo)
{
_repository = repo;
}
[HttpGet]
public ActionResult Index()
{
ViewBag.Data = _repository.FetchAll();
return View();
}
Any help at all would be much appreciated.
The error means that Autofac isn't able to find the assembly that host the IRepository type.
To resolive it, you have to specify where to find the type in your autofac configuration. You can do it by specifying the assemblyname on the service attribute. The syntax is namespace.typeName, assemblyName
<autofac>
<components>
<component
type="projectnamespace.Repositories.OrderRepository, assemblyName"
service="projectnamespace.Repositories.IRepository, assemblyName" />
</components>
</autofac>
In your case, it seems that the assemblyName is projectName
I've just read the docs on PostSharp.net about Importing Dependencies from the Target Object and need some clarification from WCF service perspective.
This is my trimmed cache aspect in which I'm trying to use ICache via Unity:
[Serializable]
public class CacheAspect : OnMethodBoundaryAspect, IInstanceScopedAspect
{
[IntroduceMember(Visibility = Visibility.Family, OverrideAction = MemberOverrideAction.Ignore)]
[CopyCustomAttributes(typeof(ImportAttribute))]
[Import(typeof(ICache))]
public ICache Cache { get; set; }
[ImportMember("Cache", IsRequired = true)]
public Property<ICache> CacheProperty;
public override void OnEntry(MethodExecutionArgs args)
{
var cache = this.CacheProperty.Get();
}
object IInstanceScopedAspect.CreateInstance(AdviceArgs adviceArgs)
{
return this.MemberwiseClone();
}
void IInstanceScopedAspect.RuntimeInitializeInstance()
{
var container = new UnityContainer();
container.LoadConfiguration();
var distributedCache = container.Resolve<DistributedCache>();
this.CacheProperty.Set(distributedCache);
}
}
My issue is with the RuntimeInitializeInstance method.
I'd like to know if setting the CacheProperty in this method is the correct approach or should I be doing it differently ?
Initializing the ICache dependency in the [RuntimeInitializeInstance] method is one of the correct approaches, but the provided implementation is not efficient, because you create and configure a new container instance every time.
Usually, it's more convenient to let the DI container to resolve the dependencies for you instead of setting them manually.
The [IntroduceMember] attribute tells PostSharp to add the Cache property directly to your service class. When resolving the service instance during run-time, Unity container can set this Cache property for you automatically.
You can tell Unity to set the property value by annotating it with the [Dependency] attribute (Annotating Objects for Property (Setter) Injection). For this attribute to be copied to your service class you also need to apply the [CopyCustomAttributes] attribute.
[IntroduceMember(Visibility = Visibility.Family, OverrideAction = MemberOverrideAction.Ignore)]
[CopyCustomAttributes(typeof(DependencyAttribute))]
[Dependency]
public ICache Cache { get; set; }
The attributes in your example were copied from the documentation and demonstrate the same principle for the MEF container.
What I am trying to achieve: Have Unity load the mappings from a configuration file, then in source code resolve the types which were loaded from said configuration file
App.Config
<register type="NameSpace.ITill, ExampleTightCoupled" mapTo="NameSpace.Till, NameSpace" />
<register type="NameSpace.IAnalyticLogs, NameSpace" mapTo="NameSpace.AnalyticLogs, NameSpace" />
Code
IUnityContainer container;
container = new UnityContainer();
// Read interface->type mappings from app.config
container.LoadConfiguration();
// Resolve ILogger - this works
ILogger obj = container.Resolve<ILogger>();
// Resolve IBus - this fails
IBus = container.Resolve<IBus>();
Issue: Sometimes IBus will be defined in the App.config, and sometimes it will not be there. When I try and resolve an interface/class and it does not exist I get an exception.
Can someone educate me here?
Thanks,
Andrew
What version of Unity are you using? In v2+ there is an extension method:
public static bool IsRegistered<T>(this IUnityContainer container);
so you can do
if (container.IsRegistered<IBus>())
IBus = container.Resolve<IBus>();
An extension method would make this nicer
public static class UnityExtensions
{
public static T TryResolve<T>(this IUnityContainer container)
{
if (container.IsRegistered<T>())
return container.Resolve<T>();
return default(T);
}
}
// TryResolve returns the default type (null in this case) if the type is not configured
IBus = container.TryResolve<IBus>();
Also check out this link: Is there TryResolve in Unity?
I've literally just started using the Unity Application Blocks Dependency Injection library from Microsoft, and I've come unstuck.
This is my IoC class that'll handle the instantiation of my concrete classes to their interface types (so I don't have to keep called Resolve on the IoC container each time I want a repository in my controller):
public class IoC
{
public static void Intialise(UnityConfigurationSection section, string connectionString)
{
_connectionString = connectionString;
_container = new UnityContainer();
section.Configure(_container);
}
private static IUnityContainer _container;
private static string _connectionString;
public static IMovementRepository MovementRepository
{
get { return _container.Resolve<IMovementRepository>(); }
}
}
So, the idea is that from my Controller, I can just do the following:
_repository = IoC.MovementRepository;
I am currently getting the error:
Exception is:
InvalidOperationException - The type
String cannot be constructed. You must
configure the container to supply this
value.
Now, I'm assuming this is because my mapped concrete implementation requires a single string parameter for its constructor. The concrete class is as follows:
public sealed class MovementRepository : Repository, IMovementRepository
{
public MovementRepository(string connectionString) : base(connectionString) { }
}
Which inherits from:
public abstract class Repository
{
public Repository(string connectionString)
{
_connectionString = connectionString;
}
public virtual string ConnectionString
{
get { return _connectionString; }
}
private readonly string _connectionString;
}
Now, am I doing this the correct way? Should I not have a constructor in my concrete implementation of a loosely coupled type? I.e. should I remove the constructor and just make the ConnectionString property a Get/Set so I can do the following:
public static IMovementRepository MovementRepository
{
get
{
return _container.Resolve<IMovementRepository>(
new ParameterOverrides
{
{
"ConnectionString", _connectionString
}
}.OnType<IMovementRepository>() );
}
}
So, I basically wish to know how to get my connection string to my concrete type in the correct way that matches the IoC rules and keeps my Controller and concrete repositories loosely coupled so I can easily change the DataSource at a later date.
EDIT 09:52:
Just to re-iterate what I'm after. I want to know the correct way to pass the ConnectionString or an IRepositoryConfiguration object (prefer that idea, thanks Mc) to a concrete class from Unity. I'm not too fussed on what I pass, just how I pass it whilst maintaining loose coupling.
You can configure the unity container for this:
IUnityContainer container = new UnityContainer()
.RegisterType<IMovementRepository, MovementRepository>(
new InjectionConstructor("connectionstring goes here"));
in XLM that would probably be something like this:
<type type="foo.IMovementRepository,foo" mapTo="foo.MovementRepository,foo">
<typeConfig extensionType="Microsoft.Practices.Unity.Configuration.TypeInjectionElement, Microsoft.Practices.Unity.Configuration">
<constructor>
<param name="connectionString" parameterType="System.String" >
<value value="conectionstring goes here" type="System.String"/>
</param>
</constructor>
</typeConfig>
</type>
or wrap the connectionstring as mcaaltuntas points out.
Probably the most straight forward way to do this is to set up a constructor section for your mapped type in the unity configuration and inside the constructor section have a parameter element for the connection string that passes in a name value for a connection string you have defined in the connectionStrings section of your web configuration.
Inside your constructor code for the Repository class, have some code that uses the name value of the connection string to get the full connection string from the connectionStrings section.
EDIT:
Here's an example for you using Unity 2.0
In your web.config, specify the connection string and a mapping for unity to map an IRepository<T> to a SqlRepository<T>. Based on your other questions, we'll assume that IRepository<T> is in your model project and SqlRepository<T> is in your DAL project.
<?xml version="1.0"?>
<configuration>
<configSections>
<section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration" />
</configSections>
<connectionStrings>
<add name="SqlConnection" connectionString="data source=(local)\SQLEXPRESS;Integrated Security= SSPI; Initial Catalog= DatabaseName;" providerName="System.Data.SqlClient"/>
</connectionStrings>
<unity>
<containers>
<container>
<types>
<type type="ModelProject.IRepository`1, ModelProject" mapTo="DALProject.SqlRepository`1, DALProject">
<constructor>
<param name="connectionString">
<value value="SqlConnection" />
</param>
</constructor>
</type>
</types>
</container>
</containers>
</unity>
</configuration>
Now for the IRepository<T> interface in the model project. In this example, I'm also going to be using LINQ to SQL to return objects from the SQL Database
namespace ModelProject
{
/// <summary>
/// Interface implemented by a Repository to return
/// <see cref="IQueryable`T"/> collections of objects
/// </summary>
/// <typeparam name="T">Object type to return</typeparam>
public interface IRepository<T>
{
IQueryable<T> Items { get; }
}
}
And the SQLRepository<T> class in the DAL project
namespace DALProject
{
/// <summary>
/// Generic class for returning an <see cref="IQueryable`T"/>
/// collection of types
/// </summary>
/// <typeparam name="T">object type</typeparam>
public class SqlRepository<T> : IRepository<T> where T : class
{
private Table<T> _table;
public SqlRepository(string connectionString)
{
// use the connectionString argument value to get the
// connection string from the <connectionStrings> section
// in web.config
string connection = ConfigurationManager.ConnectionStrings[connectionString].ConnectionString;
_table = (new DataContext(connection)).GetTable<T>();
}
/// <summary>
/// Gets an <see cref="IQueryable`T"/> collection of objects
/// </summary>
public IQueryable<T> Items
{
get { return _table; }
}
}
}
Let's also use a custom controller factory to allow unity to return controllers for us. This way, unity will inject any dependencies that the controllers have
In global.asax
namespace WebApplicationProject
{
public class MvcApplication : System.Web.HttpApplication
{
public static void RegisterRoutes(RouteCollection routes)
{
// your routes
}
protected void Application_Start()
{
RegisterRoutes(RouteTable.Routes);
ControllerBuilder.Current.SetControllerFactory(new UnityControllerFactory());
}
}
public class UnityControllerFactory : DefaultControllerFactory
{
private IUnityContainer _container;
public UnityControllerFactory()
{
_container = new UnityContainer();
var controllerTypes = from t in Assembly.GetExecutingAssembly().GetTypes()
where typeof(IController).IsAssignableFrom(t)
select t;
foreach (Type t in controllerTypes)
_container.RegisterType(t, t.FullName);
UnityConfigurationSection section = (UnityConfigurationSection)ConfigurationManager.GetSection("unity");
section.Configure(_container);
}
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
// see http://stackoverflow.com/questions/1357485/asp-net-mvc2-preview-1-are-there-any-breaking-changes/1601706#1601706
if (controllerType == null) { return null; }
return (IController)_container.Resolve(controllerType);
}
}
}
And Here's a controller example. PageSize might be defined on a base controller or on the controller as a property.
namespace WebApplicationProject.Controllers
{
public class CustomersController : Controller
{
private IRepository<Customer> _customerRepository;
public int PageSize { get; set; }
public CustomersController() { }
public CustomersController(IRepository<Customer> customerRepository)
{
this._customerRepository = customerRepository;
// let's set it to 10 items per page.
this.PageSize = 10;
}
public ViewResult List(string customerType, int page)
{
var customerByType = (customerType == null) ?
customerRepository.Items : customerRepository.Items.Where(x => x.CustomerType == customerType);
int totalCustomers = customerByType.Count();
ViewData["TotalPages"] = (int)Math.Ceiling((double)totalCustomers/ PageSize);
ViewData["CurrentPage"] = page;
ViewData["CustomerType"] = customerType;
// get the right customers from the collection
// based on page number and customer type.
return View(customerByType
.Skip((page - 1) * PageSize)
.Take(PageSize)
.ToList()
);
}
}
}
When the customers list controller action is invoked, unity will correctly instantiate an instance of SqlRepository<Customer> for the controller and inject this into the constructor. the connectionString string used for SqlRepository<T> is set in the unity configuration and is passed into the constructor for a typed SqlRepository<T>.
I didnt use Unity but I have used configuration objects in these situations. For example you can write your code like this
class Configuration:IRepositoryConfiguration,IMailConfiguration
{
private string connectionString;
//IRepository configurations
public string ConnectionString
{
//read connection string from somewhere
get { return connectionString; }
}
//EMail configurations
public string Smtp
{
get { return smpt; }
}
}
interface IRepositoryConfiguration
{
string ConnectionString { get;}
}
public abstract class Repository
{
public Repository(IRepositoryConfiguration configuration)
{
_connectionString = configuration.ConnectionString;
}
public virtual string ConnectionString
{
get { return _connectionString; }
}
private readonly string _connectionString;
}
So you can register IRepositoryConfiguration and Unity will resolve your configuration objects. Also you can add extra parameters in this approach easily.
Update
I think it is ok to have a constructor that accepts IRepositoryConfiguration object in your concrete classes(abstract repository and MovementRepository). Becase they are implementations details and concrete implementations of IMovementRepository.so they need to know connection string.
Setter or Constructor Injection
I prefer constructor injection over setter injection. I think constructor injection leads more discoverable APIs. in Constructor injection as soon as when you want to instantiate object, you see what an object needs to work but in Setter injection you must learn which property to set to use API. For detailed information you can read Constructor ve Setter Injection
I ll add another way :)
You can use Injection parameters that get passed into the constructor when you register a type. This way you can still use constructor injection.
class Repository : IRepository {
readonly string m_ConnectionString;
public Repository(string connectionString) {
ConnectionString = connectionString;
}
}
//When registering
container.RegisterType<IRepository, Repository>(new InjectionConstructor("connectionstring"));