Update:
This is an mvc plugin project, using MEF to get the controllers and actions at run time. http://www.fidelitydesign.net/?p=104
I added a new project and in its class I added an export of a type that is already being composed.
[Export(typeof(IController)), ExportMetadata("Name", "Clocks")]
public class ClocksController : Controller
{
public XmlActionResult Index()
{
var p = DeviceLogic.GetUnassigned;
}
[Import(typeof(DeviceLogic))]
DeviceLogic DeviceLogic { get; set; }
}
This gets composed in another project:
[Export]
public class ImportControllerFactory : DefaultControllerFactory
{
[ImportMany]
private IEnumerable<PartFactory<IController, IControllerMetadata>> ControllerFactories;
}
Application Start
[ImportMany]
private IEnumerable<ImportControllerFactory> ControllerFactories;
Controller factories is null, until I actually compose the parts
container.ComposeParts(this);
thats working fine, so I decided to try and emulate this to get devicelogic to appear in the project im having trouble with.
I created an emptry interface (IEmpty) for testing and tried this:
[Export(typeof(IEmpty))]
public class RequestProcessor : IEmpty
{
[Import(typeof(DeviceLogic))]
DeviceLogic DeviceLogic { get; set; }
}
and in my applciation start added
[ImportMany]
private IEnumerable<IEmpty> TestMef;
This is filled with the one instance after composition, so this seems to have worked. My question is does anyone have any suggestions as to why devicelogic is null in requestprocessor but not in clocksController.
You need to call MEF's SatisfyImportsOnce method after your instantiation :
YourMEFContainter.SatisfyImportsOnce(dataTransfer)
Related
I have a shared project that I put my shared and base logic in to reuse in other projects and a Normal asp.net core project on top of it.
In the Shared base project I have:
class DbContextBase : DbContext
{
public DbSet<ActivityLog> ActivityLogs { get; set; }
public DbSet<Event> Events { get; set; }
SaveChanges(...)
}
class MyEventProcessor
{
private readonly DbContextBase _databaseContext;
public MyEventProcessor(DbContextBase databaseContext)
{
_databaseContext=databaseContext;
}
public void AddEvent(Event e){}
public void ProcessEvent(Event e){}
}
In the .net core webApi one I have my domain specific logic
class MyDomainDbContext : DbContextBase
{
public DbSet<User> Users{ get; set; }
}
class UserRepository
{
private readonly MyDomainDbContext _databaseContext;
public UserRepository(MyDomainDbContext databaseContext){_databaseContext=databaseContext;}
}
public class Startup
{
public Startup(IConfiguration configuration)
{
services.AddDbContext<MyDomainDbContext>([options]);
services.AddScoped<UserRepository>();
services.AddScoped<EventProcessor>();
}
}
The problem is, this way it fails on startup not being able to find DbContextBase because it is not registered.
I thought of changing the registeration to an interface like below, but then obviously I won't have access to my domain's DbSets in my repositories.
services.AddDbContext<IDbContextBase,MyDomainDbContext>([options]);
So the question is, how do I set this so that MyEventProcessor and UserRepository can read and write into the same Database context.
You need to register both types: DbContextBase and MyDomainDbContext, however the point is to reuse the same instance for both cases, in order to achieve that you can register them in a following way:
services.AddDbContext<MyDomainDbContext>([options]);
services.AddScoped<DbContextBase, MyDomainDbContext>(sp => sp.GetRequiredService<MyDomainDbContext>());
That way, you'll be able to inject both types, and both types will actually be the same instance, which you can easily check using GetHashCode or similar.
I am designing a NuGet package that will be consumed by my application. Due to the project's already implemented architecture, I need to provide a way to instantiate objects using dependency injection both for MVC and Web API outside my controller scope.
Currently I have a class that works in MVC projects, by instantiating objects using the DependencyResolver
public abstract class MyBaseClass<T> where T : class
{
public static T Instance
{
get
{
return DependencyResolver.Current.GetService<T>();
}
}
}
However, when consuming this same class from a WebAPI project, the DependencyResolver is not present, so Im not able to retrieve any object.
I have tried to access the dependency resolver via the HttpContext but have been unsuccessfull. Do you have any way I can access it through a NuGet package?
Thanks!
If it's possible, I'd suggest avoid the service locator pattern and inject the dependency through the constructor instead:
public abstract class MyBaseClass<T> where T : class
{
public MyBaseClass(T instance)
{
Instance = instance;
}
public T Instance { get; }
}
This will allow you to use your package through any "main" entry point (e.g. MVC or WebAPI) that you choose. At that point, it would be the responsibility of the consumer to provide the necessary dependency resolution strategy.
Here's an example of how a consumer (in this case a WebAPI service) of the package would implement the above code:
public class MyWebApiClass : MyBaseClass<MyDependency>
{
public MyWebApiClass(MyDependency resolvedDependency) : base(resolvedDependency) { }
}
public class MyDependency
{
public string Foo { get; set; }
public MyDependency()
{
Foo = "Bar";
}
}
Then the consuming service would also register those dependencies:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
services.AddTransient<MyDependency>();
services.AddTransient<MyWebApiClass>();
}
... and inject as needed, allowing the framework to resolve the dependencies (IoC at work):
[Route("api/[controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
private readonly MyWebApiClass _myWebApiClass;
public ValuesController(MyWebApiClass myWebApiClass)
{
_myWebApiClass = myWebApiClass;
}
// GET api/values
[HttpGet]
public ActionResult<IEnumerable<string>> Get()
{
return new string[] { _myWebApiClass.Instance.Foo };
}
}
Making a call to the GET endpoint above, we can see our instance being resolved in MyBaseClass:
Working on web api using EF codefirst approach.
I want to use Dependency injection using Unity framework.
i downloaded--Unity.webapi, it addeds few unity files(unityconfig, unityresolver). my entities i registered as like attachment.
but my codefirst entities not implements any interfaces, all are plain code first classes. now i want to write code in my controllers. how to write ?
public static class UnityConfig
{
public static void RegisterComponents()
{
var container = new UnityContainer();
container.RegisterType(typeof(IGenericRepository<>), typeof(GenericRepository<ApplicationDbContext,PolicyInfo>));
container.RegisterType(typeof(IGenericRepository<>), typeof(GenericRepository<ApplicationDbContext, LossInformation>));
container.RegisterType(typeof(IGenericRepository<>), typeof(GenericRepository<ApplicationDbContext, Manufacturer>));
container.RegisterType(typeof(IGenericRepository<>), typeof(GenericRepository<ApplicationDbContext, ModelVariant>));
GlobalConfiguration.Configuration.DependencyResolver = new UnityDependencyResolver(container);
}
}
class
public class **PolicyInfo**
{
[Key]
public int PolicyId { get; set; }
[Required]
public string Manufacturer { get; set; }
[Required]
[DataType(DataType.Date)]
public DateTime PolicyIssuedDate { get; set; }
}
controller:
[RoutePrefix("api/PolicyInfo")]
public class PolicyInfoController : ApiController
{
GenericRepository<ApplicationDbContext, PolicyInfo> policycontext;
public PolicyInfoController()
{
this.policycontext = new GenericRepository<ApplicationDbContext, PolicyInfo>();
}
}
I hope this is not write way to create context object. because i written PolicyInfo object at constructor level. please suggest any one.
One of the key concepts behind Inversion of Control (IoC) and Dependency Injection (DI) is precisely not to have to manually instantiate the required dependencies inside the consumer class but those dependencies to get injected into the class.
So if you are using Unity or any other framework, the goal is to suppress the line where you are creating the object context by a parameter in this case in the constructor of your API Controller.
So you if your IoC container is properly configured you should be able to get a reference to the GenericRepository using e.g, constructor injection:
Try this:
[RoutePrefix("api/PolicyInfo")]
public class PolicyInfoController : ApiController
{
IGenericRepository<ApplicationDbContext, PolicyInfo> policycontext;
public PolicyInfoController(IGenericRepository<ApplicationContext,PolicyInfo> policyContext)
{
//use the context here... e.g.: Save the reference to the instance field.
this.policyContext = policyContext;
}
}
However, I would suggest a bit more of abstraction in your code in order to make it clearer and more efficient.
Take a look a this article, although a little old, still applies perfectly to your problem. Hope this helps.
i was reading a write up on easily dependency injection in ASP.Net MVC 6 from this url http://weblogs.asp.net/scottgu/introducing-asp-net-5
they show how very easily we can inject dependency into project
1st one
namespace WebApplication1
{
public class TimeService
{
public TimeService()
{
Ticks = DateTime.Now.Ticks.ToString();
}
public String Ticks { get; set; }
}
}
register the time service as a transient service in the ConfigureServices method of the Startup class:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddTransient<TimeService>();
}
public class HomeController : Controller
{
public TimeService TimeService { get; set; }
public HomeController(TimeService timeService)
{
TimeService = timeService;
}
public IActionResult About()
{
ViewBag.Message = TimeService.Ticks + " From Controller";
System.Threading.Thread.Sleep(1);
return View();
}
}
2nd one
public class HomeController : Controller
{
[Activate]
public TimeService TimeService { get; set; }
}
now see the second code. are they trying to say that if we use [Activate] attribute then we do not have to instantiate TimeService by controller constructor injection?
just tell me if we use [Activate] attribute then what will be the advantage ?
if we use [Activate] attribute then what line of code we can eliminate from 1st same code. thanks
The differences between the two code blocks are indeed that the first one leverages Constructor Injection to resolve the dependency on TimeService, while the second example marks a property as one that needs resolving using Property Injection.
What this means is simply that the following constructor becomes redundant:
public HomeController(TimeService timeService)
{
TimeService = timeService;
}
As to why one would opt for Constructor versus Property Injection, I find that trying to have a list of your dependencies clearly listed out in your constructor highlights when a class becomes too dependent, which raises concerns as to what a class is trying to accomplish and, subsequently, makes it a candidate for refactoring.
Property Injection via [Activate] will not be supported from beta5 onwards.
I am trying to use MEF in my application, but I have problem with the Import.
[Import (typeof(IUserServices ))]
public IUserServices UserService { get; private set; }
This does not work and UserService is always null.
But using the ImportContstructor in the same class works perfectly:
[ImportingConstructor ]
public MainWindowVM(
IUIVisualizerService uiVisualizer,
IViewAwareStatus viewAwareStatus,
IMessageBoxService messageBoxService,
IManager mwManager,
TagItemModel tagModel,
ILibraryModel documentModel,
ILibraryServices libraryServices,
ILogServices logServices ,
IUserServices userServices)
Can anybody help me in the issue. I already spend hours, but did not find any solution. Thanks!!!
The property will only be set by MEF after the constructor is fully executed. When are you checking if the property is null?
I'm using ChinchV2 together with MefedMVVM to create the container.
Here the code, which provides the export:
[PartCreationPolicy(CreationPolicy.Shared)]
[Export (typeof(IUserServices ))]
public class TestUserServices:IUserServices
{
public void GetSettings(Action<HubSettings, Exception> callback)
{
var dPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().GetName().CodeBase).Remove(0, 6);
callback(new HubSettings {DataPath = dPath}, null);
}
}