Activation error occurred while trying to get instance of type IBackupTableStorageService, key "" StructureMap library - inversion-of-control

I am facing issue of mapping. My solution is as below.
I have two projects
1. Azure Function (v1) project with Framework: .Net Framework 4.7.2
2. Class Library with Framework: .Net Framework 4.7.2
In 1st project i have an azure function which is triggering using Queue and call my function BeginBackup(CancellationToken token, DateTime.Now()) which exist in my concreate class.
I am calling my function as below from my Azure function.
DependencyContext.Instance.Locator.GetInstance<IBackupTableStorageService>().BeginBackup(cancellationToken, SystemTime.UtcNow());
My DependencyContext.cs class is below.
using ClassLibrary1.BackupTableStorage;
using CommonServiceLocator;
using StructureMap;
using System;
using System.Collections.Generic;
namespace AzureFunctionsProject.Functions
{
public interface IDependencyContext
{
IServiceLocator Locator { get; }
}
public class DependencyContext : IDependencyContext
{
private static volatile IDependencyContext _instance;
private static readonly object SyncRoot = new Object();
public static IDependencyContext Instance
{
get
{
if (_instance == null)
{
lock (SyncRoot)
{
if (_instance == null)
{
_instance = new DependencyContext();
}
}
}
return _instance;
}
set => _instance = value;
}
public IServiceLocator Locator { get; private set; }
public DependencyContext()
{
Build();
}
private void Build()
{
var registry = new Registry();//Registry is the class belongs to StructureMap.
var container = new Container();
var serviceLocatorProvider = new StructureMapServiceLocator(container);
ServiceLocator.SetLocatorProvider(() => serviceLocatorProvider);
Locator = serviceLocatorProvider;
// register the container itself
registry.For<IServiceLocator>().Use(ServiceLocator.Current);
// Apply the registry to the container
container.Configure(x =>
{
x.AddRegistry<Domain.Registry>();
x.AddRegistry(registry);
});
}
}
public class StructureMapServiceLocator : ServiceLocatorImplBase
{
private IContainer Container { get; set; }
public StructureMapServiceLocator(IContainer container)
{
Container = container;
}
protected override object DoGetInstance(Type serviceType, string key)
{
if (string.IsNullOrEmpty(key))
{
return Container.GetInstance(serviceType);
}
return Container.GetInstance(serviceType, key);
}
protected override IEnumerable<object> DoGetAllInstances(Type serviceType)
{
foreach (object obj in Container.GetAllInstances(serviceType))
{
yield return obj;
}
}
}
}
I have another Registery class which i have created which have mapping of my interface with my concrete class.
Registery.cs file is below.
namespace ClassLibrary1.Domain
{
public class Registry: StructureMap.Registry
{
public Registry()
{
// The Localization Service needs to be passed a function to record exceptions
For<ILocalizationService>().Use<LocalizationService>()
.Ctor<LocalizationService.LogException>().Is(context => CreateExceptionLogger(context));
For<ICloudStorageWrapper>().Use<CloudStorageWrapper>();
For<IBackupTableStorageService>().Use<BackupTableStorageService>();
}
private LocalizationService.LogException CreateExceptionLogger(IContext context)
{
return (ex, c, m) =>
{
var logger = context.GetInstance<ILogicalOperationsLogger>();
logger.ErrorException(m, ex);
};
}
}
}
Like wise i have my Interface and respected to concreate class which has the definition of my method BeginBackup(CancellationToken token, DateTime.Now());
I am getting exception in DoGetInstance method in DependencyContext.cs class.
I am new in IoC and dependency injection, please let me know what i am doing wrong, if anything required to make question more clear please let me know.

Try to move the registration for IServiceLocator into the configure action. You can also remove the Registry-object you created:
private void Build()
{
var container = new Container();
var serviceLocatorProvider = new StructureMapServiceLocator(container);
ServiceLocator.SetLocatorProvider(() => serviceLocatorProvider);
Locator = serviceLocatorProvider;
// Apply the registry to the container
container.Configure(x =>
{
// register the container itself
x.For<IServiceLocator>().Use(serviceLocatorProvider);
x.AddRegistry<Domain.Registry>();
});
}

Related

Resolve Castle Windsor dependency by argument name

Given That
Component.For<IService>().ImplementedBy<SecretService>().Named("secretService")
Component.For<IService>().ImplementedBy<PublicService>().Named("publicService")
And
class Foo{
public Foo(IService publicService){ ...... }
}
And
class Bar{
public Bar(IService secretService){ ...... }
}
Then how can i achieve the following
Foo and Bar should get instances of publicService and secretService respectively, entirely based on name of their constructor parameters.
I have now made it to work using a custom SubDependencyResolver, i added this to the container and now it injects the implementation by name
public class ByParameterNameResolver : ISubDependencyResolver
{
private readonly IKernel kernel;
public ByParameterNameResolver(IKernel kernel)
{
this.kernel = kernel;
}
public virtual bool CanResolve(CreationContext context, ISubDependencyResolver contextHandlerResolver, ComponentModel model, DependencyModel dependency)
{
if (dependency.TargetItemType == null)
return false;
if (string.IsNullOrWhiteSpace(dependency.DependencyKey))
return false;
return kernel.HasComponent(dependency.DependencyKey);
}
public virtual object Resolve(CreationContext context, ISubDependencyResolver contextHandlerResolver, ComponentModel model, DependencyModel dependency)
{
return kernel.Resolve(dependency.DependencyKey, dependency.TargetItemType);
}
}

How to change database schema on runtime in EF7 or EF core

My database have different schema depending on user selections on runtime.
My code is below:
public partial class FashionContext : DbContext
{
private string _schema;
public FashionContext(string schema) : base()
{
_schema = schema;
}
public virtual DbSet<Style> Styles { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder options)
{
options.UseSqlServer(#"Server=.\sqlexpress;Database=inforfashionplm;Trusted_Connection=True;");
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Style>()
.ToTable("Style", schema: _schema);
}
}
Upon testing. I created a context instance with 'schema1'.
So far so good.
But when I create another context instance with different schema 'schema2', the resulting data in which the schema is still on 'schema1'.
Here is the implementation:
using (var db = new FashionContext("schema1"))
{
foreach (var style in db.Styles)
{
Console.WriteLine(style.Name);
}
}
Console.ReadLine();
Console.Clear();
using (var db = new FashionContext("schema2"))
{
foreach (var style in db.Styles)
{
Console.WriteLine(style.Name);
}
}
Console.ReadLine();
Later I noticed that the OnModelCreating is called only one time, so it is never called again when you create a new context instance of the same connection string.
Is it possible to have dynamic schema on runtime? Note: this is possible in EF6
One of possible way was mentioned above, but briefly, so I will try to explain with examples.
You ought to override default ModelCacheKeyFactory and ModelCacheKey.
ModelCachekeyFactory.cs
internal sealed class CustomModelCacheKeyFactory<TContext> : ModelCacheKeyFactory
where TContext : TenantDbContext<TContext>
{
public override object Create(DbContext context)
{
return new CustomModelCacheKey<TContext>(context);
}
public CustomModelCacheKeyFactory([NotNull] ModelCacheKeyFactoryDependencies dependencies) : base(dependencies)
{
}
}
ModelCacheKey.cs, please review Equals and GetHashCode overridden methods, they are not best one and should be improved.
internal sealed class ModelCacheKey<TContext> : ModelCacheKey where TContext : TenantDbContext<TContext>
{
private readonly string _schema;
public ModelCacheKey(DbContext context) : base(context)
{
_schema = (context as TContext)?.Schema;
}
protected override bool Equals(ModelCacheKey other)
{
return base.Equals(other) && (other as ModelCacheKey<TContext>)?._schema == _schema;
}
public override int GetHashCode()
{
var hashCode = base.GetHashCode();
if (_schema != null)
{
hashCode ^= _schema.GetHashCode();
}
return hashCode;
}
}
Register in DI.
builder.UseSqlServer(dbConfiguration.Connection)
.ReplaceService<IModelCacheKeyFactory, CustomModelCacheKeyFactory<CustomContext>>();
Context sample.
public sealed class CustomContext : TenantDbContext<CustomContext>
{
public CustomContext(DbContextOptions<CustomContext> options, string schema) : base(options, schema)
{
}
}
You can build the model externally and pass it into the DbContext using DbContextOptionsBuilder.UseModel()
Another (more advanced) alternative is to replace the IModelCacheKeyFactory to take schema into account.
I found a way to recreate the compiled model on each context creation.
public partial class MyModel : DbContext {
private static DbConnection _connection
{
get
{
//return a new db connection
}
}
private static DbCompiledModel _model
{
get
{
return CreateModel("schema name");
}
}
public MyModel()
: base(_connection, _model, false)
{
}
private static DbCompiledModel CreateModel(string schema)
{
var modelBuilder = new DbModelBuilder();
modelBuilder.HasDefaultSchema(schema);
modelBuilder.Entity<entity1>().ToTable(schema + ".entity1");
var builtModel = modelBuilder.Build(_connection);
return builtModel.Compile();
}
}

How can I achieve the following using IOC?

I want to use IOC with my service and I want to instead inject a class not an interface in the constructor as below in the services layer but I do not want to create a new object from the calling layer like var service = new InvoiceService(new ChangeInvoiceDueDateCommand()) instead I want to create something like this from my controller in MVC where the IInvoiceService is injected into the controller constructor but the problem I see is that
public InvoiceController(IInvoiceService invoiceService, IMapper mapper)
{
_invoiceService = invoiceService;
_mapper = mapper;
}
and then called like this
public ActionResult ChangeInvoiceDueDate(InvoiceChangeDueDateViewModel invoiceChangeDueDateViewModel )
{
var request = _mapper.Map<InvoiceChangeDueDateViewModel, ChangeInvoiceDuedateRequest>(invoiceChangeDueDateViewModel);
InvoiceChangeDueDateResponse response = _invoiceService.ChangeDueDate(request);
return View();
}
Service Layer
public class InvoiceService : IInvoiceService
{
private readonly ChangeInvoiceDueDateCommand _changeInvoiceDueDateCommand;
public InvoiceService(ChangeInvoiceDueDateCommand changeInvoiceDueDateCommand)
{
_changeInvoiceDueDateCommand = changeInvoiceDueDateCommand;
}
public InvoiceChangeDueDateResponse ChangeDueDate(ChangeInvoiceDuedateRequest invoiceChangeDueDateRequest)
{
_changeInvoiceDueDateCommand.Execute(invoiceChangeDueDateRequest);
return new InvoiceChangeDueDateResponse {Status = new Status()};
}
}
Command
public class ChangeInvoiceDueDateCommand : ICommand<ChangeInvoiceDuedateRequest>
{
private readonly IRepository<Invoice> _invoiceRepository;
readonly InvoiceDueDateChangeValidator _validator;
public ChangeInvoiceDueDateCommand(IRepository<Invoice> invoiceRepository)
{
_invoiceRepository = invoiceRepository;
_validator = new InvoiceDueDateChangeValidator();
}
public void Execute(ChangeInvoiceDuedateRequest request)
{
if (_validator.IsDuedateValid(request.NewDuedate))
{
Invoice invoice = _invoiceRepository.GetById(request.Id);
invoice.ChangedDueDate(request.NewDuedate);
_invoiceRepository.SaveOrUpdate(invoice);
}
else
{
throw new InvalidDueDateException();
}
}
}
ICommand
public interface ICommand<T> where T : IRequest
{
void Execute(T request);
}
IRequest
public interface IRequest
{
int Id { get; set; }
}
I worked it out. It was just a Windsor syntax issue. It ended up being as simple as registering the Command using the container.Register(Component.For<ChangeInvoiceDueDateCommand>());

How would I use Autofac as the primary container in Catel?

Is there a way I can use Autofac as my primary container for Catel?
I've seen that there is support for Unity, Ninject, MEF, Windsor, and Unity, but there is no mention of Autofac integration.
We haven't created an helper for Autofac, nor are we planning to write one.
You have the following options:
1) Write the Helper class yourself (see the others for examples) and register it, then the ServiceLocator can sync it
2) In the latest prerelease of Catel (3.7 prerelease) we have introduced the IDependencyResolver. You can implement this interface on your Autofac container and register that in the ServiceLocator. Note though that we don't have full support for this so it might cause side-effects.
3) Use the ServiceLocator in Catel
edit on 2013-09-14
4) If you are interested in the latest version of Catel (nightly build), you can now replace the default service locator with your implementation:
Issue details: https://catelproject.atlassian.net/browse/CTL-175
Documentation: https://catelproject.atlassian.net/wiki/pages/viewpage.action?pageId=622682#IoC(ServiceLocatorandTypeFactory)-Replacingthedefaultcomponents
Here is my solution for Catel 3.8 and Autofac (should work for other 3rd party containers too).
I wrote an implementation for IDependencyResolver backed by an Autofac container and an implementation for IServiceLocator. The former contains the applications 3rd party IoC configuration and logic. The latter is used to grab all type and instance registrations of Catels modules and foreward them to Autofac.
The basic strategy is
Create and configure a 3rd party container
Use it to instanciate (partially customized) Catel IoC components and introduce them to Catels IoC configuration
Let Catel do its type and instance registration using the previously created (customized) implementations and foreward them to the third party container
So here is my implementation for the IServiceLocator:
internal class CustomServiceLocator : IServiceLocator
{
private readonly CustomDependencyResolver _dependencyResolver;
public CustomServiceLocator(CustomDependencyResolver dependencyResolver)
{
_dependencyResolver = dependencyResolver;
}
public object GetService(Type serviceType)
{
throw new NotImplementedException();
}
public RegistrationInfo GetRegistrationInfo(Type serviceType, object tag = null)
{
throw new NotImplementedException();
}
public bool IsTypeRegistered(Type serviceType, object tag = null)
{
return _dependencyResolver.CanResolve(serviceType, tag);
}
public bool IsTypeRegisteredAsSingleton(Type serviceType, object tag = null)
{
throw new NotImplementedException();
}
public void RegisterInstance(Type serviceType, object instance, object tag = null)
{
var builder = new ContainerBuilder();
IRegistrationBuilder<object, SimpleActivatorData, SingleRegistrationStyle> registrationBuilder = builder.RegisterInstance(instance);
if (tag != null)
{
registrationBuilder.Keyed(tag, serviceType);
}
_dependencyResolver.UpdateContainer(builder);
}
public void RegisterType(Type serviceType, Type serviceImplementationType, object tag = null, RegistrationType registrationType = RegistrationType.Singleton,
bool registerIfAlreadyRegistered = true)
{
var builder = new ContainerBuilder();
IRegistrationBuilder<object, ConcreteReflectionActivatorData, SingleRegistrationStyle> registrationBuilder = builder.RegisterType(serviceImplementationType).As(serviceType);
if (tag != null)
{
registrationBuilder.Keyed(tag, serviceType);
}
switch (registrationType)
{
case RegistrationType.Singleton:
registrationBuilder.SingleInstance();
break;
case RegistrationType.Transient:
registrationBuilder.InstancePerDependency();
break;
default:
registrationBuilder.InstancePerDependency();
break;
}
_dependencyResolver.UpdateContainer(builder);
TypeRegistered(this, new TypeRegisteredEventArgs(serviceType, serviceImplementationType, tag, registrationType));
}
public object ResolveType(Type serviceType, object tag = null)
{
// Must be implemented. Catels ViewModelBase resolves the DependencyResolver in ctor using the ServiceLocator...Why???
return _dependencyResolver.Resolve(serviceType, tag);
}
public IEnumerable<object> ResolveTypes(Type serviceType)
{
throw new NotImplementedException();
}
public void RemoveInstance(Type serviceType, object tag = null)
{
throw new NotImplementedException();
}
public void RemoveAllInstances(Type serviceType)
{
throw new NotImplementedException();
}
public void RemoveAllInstances(object tag = null)
{
throw new NotImplementedException();
}
public bool IsExternalContainerSupported(object externalContainer)
{
throw new NotImplementedException();
}
public void RegisterExternalContainer(object externalContainer)
{
throw new NotImplementedException();
}
public void RegisterExternalContainerHelper(IExternalContainerHelper externalContainerHelper)
{
throw new NotImplementedException();
}
public void ExportInstancesToExternalContainers()
{
throw new NotImplementedException();
}
public void ExportToExternalContainers()
{
throw new NotImplementedException();
}
public bool AreAllTypesRegistered(params Type[] types)
{
return _dependencyResolver.CanResolveAll(types);
}
public object[] ResolveAllTypes(params Type[] types)
{
return _dependencyResolver.ResolveAll(types);
}
public bool AutomaticallyKeepContainersSynchronized { get; set; }
public bool CanResolveNonAbstractTypesWithoutRegistration { get; set; }
public bool SupportDependencyInjection { get; set; }
public bool AutoRegisterTypesViaAttributes { get; set; }
public bool IgnoreRuntimeIncorrectUsageOfRegisterAttribute { get; set; }
public event EventHandler<MissingTypeEventArgs> MissingType;
public event EventHandler<TypeRegisteredEventArgs> TypeRegistered;
}
And here the implementation for IDepencyResolver.
internal class CustomDependencyResolver : IDependencyResolver
{
private readonly IContainer _container;
public CustomDependencyResolver()
{
var builder = new ContainerBuilder();
builder.RegisterAssemblyTypes(AppDomain.CurrentDomain.GetAssemblies());
builder.RegisterInstance(this).SingleInstance(); // dependency of CustomServiceLocator
builder.RegisterInstance(this).As<IDependencyResolver>().SingleInstance(); // Dependency of ViewModelBase. Catels ViewModelBase resolves the DependencyResolver in ctor using the ServiceLocator...Why???
builder.RegisterType<CustomServiceLocator>().As<IServiceLocator>().SingleInstance(); // dependency of TypeFactory (subscribes to TypeRegistered event to clear its cache)
builder.RegisterType<TypeFactory>().As<ITypeFactory>().SingleInstance(); // dependency of ViewModelFactory
_container = builder.Build();
}
public bool CanResolve(Type type, object tag = null)
{
return _container.IsRegistered(type);
}
public bool CanResolveAll(Type[] types)
{
return types.All(type => _container.IsRegistered(type));
}
public object Resolve(Type type, object tag = null)
{
object obj;
if (tag == null)
{
if (_container.TryResolve(type, out obj))
return obj;
}
else
{
if (_container.TryResolveKeyed(tag, type, out obj))
return obj;
}
throw new Exception(string.Format("Could not locate any instances of contract {0}.", tag ?? type.Name));
}
public object[] ResolveAll(Type[] types, object tag = null)
{
var objects = new ArrayList();
if (tag == null)
{
foreach (Type type in types)
{
object obj;
if (_container.TryResolve(type, out obj))
{
objects.Add(obj);
}
else
{
throw new Exception(string.Format("Could not locate any instances of contract {0}.", type.Name));
}
}
}
else
{
foreach (Type type in types)
{
object obj;
if (_container.TryResolveKeyed(tag, type, out obj))
{
objects.Add(obj);
}
else
{
throw new Exception(string.Format("Could not locate any instances of contract {0}.", tag));
}
}
}
return objects.ToArray();
}
public void UpdateContainer(ContainerBuilder builder)
{
builder.Update(_container);
}
}
Putting it all together at startup:
public partial class App : Application
{
/// <summary>
/// Raises the <see cref="E:System.Windows.Application.Startup"/> event.
/// </summary>
/// <param name="e">A <see cref="T:System.Windows.StartupEventArgs"/> that contains the event data.</param>
protected override void OnStartup(StartupEventArgs e)
{
#if DEBUG
Catel.Logging.LogManager.AddDebugListener();
#endif
StyleHelper.CreateStyleForwardersForDefaultStyles();
// create the DependencyResolver and do Catel IoC configuration
CustomDependencyResolver dependencyResolver = new CustomDependencyResolver();
DependencyResolverManager.Default.DefaultDependencyResolver = dependencyResolver;
IoCConfiguration.DefaultDependencyResolver = dependencyResolver;
IoCConfiguration.DefaultServiceLocator = dependencyResolver.Resolve<IServiceLocator>();
IoCConfiguration.DefaultTypeFactory = dependencyResolver.Resolve<ITypeFactory>();
// let Catel register its dependencies
Catel.Core.ModuleInitializer.Initialize();
Catel.MVVM.ModuleInitializer.Initialize();
base.OnStartup(e);
}
}
Tradoffs and side effects: In my opinion Catels IoC implementation is a litte bit fuzzy. e.g. Sometimes the ServiceLocator is used to resolve the DependencyResolver, sometimes the other way around. I tried to figure out the most common internally used ways and cover them with my solution. A possible side effect may occure, if a type is registered to Autofacs container after application startup and the TypeFactory is not notified to clear its cache (i did not analyse the TypeFactory itself). I suggest an implementation for a TypeRegistered event in CustomDependencyResolver, subscribed by the CustomServiceLocator to foreward it to the TypeFactory.

DataAnnotations and FluentValidation not working in MVC 2 project

I have edited the original question since the same error is occurring the difference being the implementation, I have now added Ninject to the mix.
I have created a class for the validation rules
public class AlbumValidator : AbstractValidator<Album> {
public AlbumValidator() {
RuleFor(a => a.Title).NotEmpty();
}
}
I have created a ValidatorModule for Ninject
internal class FluentValidatorModule : NinjectModule {
public override void Load() {
AssemblyScanner.FindValidatorsInAssemblyContaining<AlbumValidator>()
.ForEach(result => Bind(result.InterfaceType).To(result.ValidatorType).InSingletonScope());
}
}
Here is my ValidatorFactory
public class NinjectValidatorFactory : ValidatorFactoryBase {
public override IValidator CreateInstance(Type validatorType) {
if (validatorType.GetGenericArguments()[0].Namespace.Contains("DynamicProxies")) {
validatorType = Type.GetType(string.Format("{0}.{1}[[{2}]], {3}",
validatorType.Namespace,
validatorType.Name,
validatorType.GetGenericArguments()[0].BaseType.AssemblyQualifiedName,
validatorType.Assembly.FullName));
}
return Container.Get(validatorType) as IValidator;
}
IKernel Container { get; set; }
public NinjectValidatorFactory(IKernel container) {
Container = container;
}
}
and the relevant parts from my Global
protected override void OnApplicationStarted() {
AreaRegistration.RegisterAllAreas();
RegisterRoutes(RouteTable.Routes);
var factory = new NinjectValidatorFactory(Container);
ModelValidatorProviders.Providers.Add(
new FluentValidationModelValidatorProvider(factory));
DataAnnotationsModelValidatorProvider
.AddImplicitRequiredAttributeForValueTypes = false;
}
protected override IKernel CreateKernel() {
return Container;
}
IKernel Container {
get { return new StandardKernel(new FluentValidatorModule()); }
}
I load the sample site click on the create new album link and then click the create button leaving the title empty I am then greeted with the error protected override void OnApplicationStarted() {
AreaRegistration.RegisterAllAreas();
RegisterRoutes(RouteTable.Routes);
var factory = new NinjectValidatorFactory(Container);
ModelValidatorProviders.Providers.Add(
new FluentValidationModelValidatorProvider(factory));
DataAnnotationsModelValidatorProvider
.AddImplicitRequiredAttributeForValueTypes = false;
}
protected override IKernel CreateKernel() {
return Container;
}
IKernel Container {
get { return new StandardKernel(
new Bootstrapper(),
new FluentValidatorModule()); }
}
I load up the create form and click create leaving the title empty low and behold an error
This property cannot be set to a null value.
The line it references is within the Entity Framework auto generated class, I traced the
Namespace.Contains("DynamicProxies")
and it was returning false, is this because I told EF to use a custom namespace SampleMusicStore.Web?
Or am I missing something else?
Cheers.
The problem is that Entity Framework is generating dynamic proxies on your classes, and then your system is trying to validate against the proxy classes instead of the classes you defined.
The way to resolve this is the same as this answer.