Hello Experts I have class in folowing structure
public class Apple:IApple
{
public IBall _ball{get;private set}
public Apple()
{
_ball=new Ball();
}
}
Public class Cat:ICat
{
private readonly IBall _ball;
Public Cat(IBall ball)
{
this._ball=ball
}
}
I am configuring my structure map as below (Not displayed standard registry and controller registry with controller conventions)
ObjectFactory.Container.Configure(cfg =>
{
cfg.For<IApple>().Use<Apple>();
cfg.For<ICat>.Use<Cat>();
});
When I reference ICat in Controller as below
private readonly ICat _cat;
public HomeController(ICat cat)
{
this._cat = cat;
}
I am receiving error "No default Instance is registered and cannot be automatically determined for type IBall".
Experts, please provide some suggestions.
You should register IBall like this:
cfg.For<IBall>().Use(c => ((Apple)c.GetInstance<IApple>())._ball);
Related
The package Blazored.LocalStorage is:
a library to provide access to local storage in Blazor applications
Injecting the service into a component is easy:
#inject Blazored.LocalStorage.ILocalStorageService localStorage
and if we want to inject it into the code behind:
[Inject]
private ILocalStorageService localStorage { get; set; }
But suppose I want to inject it into another service (let say for centralizing the control):
public class StorageManagement
{
public StorageManagement(LocalStorageService localStorage)
{
//How to initialize it here?
}
}
I do not know how to initialize an instance of the service in the constructor of StorageManagement and also how to set the parameters of constructor of StorageManagement in Program.cs :
builder.Services.AddSingleton(e => new StorageManagement(//?));
Just builder.Services.AddBlazoredLocalStorage(); or builder.Services.AddBlazoredLocalStorage(config => config.JsonSerializerOptions.WriteIndented = true); as it's explain in README.
Then builder.Services.AddScoped<StorageManagement>(); or builder.Services.AddScoped(p => new StorageManagement(p.GetRequiredSerice<ILocalStorageService>()));
But your service should take a ILocalStorageService not a LocalStorageService instance :
public class StorageManagement
{
public StorageManagement(ILocalStorageService localStorage)
{
//How to initialize it here?
}
}
You are not using the Interface ILocalStorageServer in your constructor, it should be
public class StorageManagement
{
private readonly ILocalStorageService LocalStorage;
public StorageManagement(ILocalStorageService localStorage)
{
LocalStorage = localStorage;
}
}
My problems is that I want to register two types for one interface:
I've checked this articles:
https://groups.google.com/forum/#!msg/structuremap-users/2T_WTAjRVJ8/HKsELqJEOi4J
https://groups.google.com/forum/#!topic/structuremap-users/75-1AV1boMw
For<IPageManager>().Singleton().Use<PageManager>().Named("pageManager");
For<IPageManager>().Singleton().Use<EnhancedPageManager>().Named("enhancedPageManager");
And in my controllers:
public class ValuesController
{
public ValuesController(IPageManager pageManger)
{
// Here I want to be instance of page Manager
}
}
public class PagesController
{
public PagesController(IPageManager enhancedPageManger)
{
// Here I want to be instance of enhancedPageManger
}
}
But the problems is that I always receive instance of enhancedPageManger.
How to fix that ?
In the documentation there are example of configuration, but not the usage: http://structuremap.github.io/glossary/#sec3
var container = new Container(c =>
{
c.For<IFoo>().Use<Foo>();
c.For<IFoo>().Add<SomeOtherFoo>();
});
Until recently I used AutoFac which had the method AsImplementedInterfaces()
which does
Register the type as providing all of its public interfaces as services (excluding IDisposable).
that means (for example a service) I have some base interface and an interface for every concerte service-class
See the simple code below:
public interface IService {}
public interface IMyService: IService
{
string Hello();
}
public class MyService: IMyService
{
public string Hello()
{
return "Hallo";
}
}
// just a dummy class to which IMyService should be injected
// (at least that's how I'd do it with AutoFac.
public class MyClass
{
public MyClass(IMyService myService) { }
}
Basically I want to inject my service's interface (so to speak) and not the concrete service.
Now I have to use StructureMap but I struggle to find what I need.
There is AddAllTypesOf<T> but this would register the concrete type.
is this even possible with StructureMap and if so how?
so, I found the answer(s)
1.
first you could use
public class TestRegistry : Registry
{
public TestRegistry()
{
Scan(x =>
{
x.TheCallingAssembly();
x.RegisterConcreteTypesAgainstTheFirstInterface();
});
}
}
this will register every concrete class against the first interface which might be too broad.
2.
if so you can use the following code I adapted from http://structuremap.github.io/registration/auto-registration-and-conventions/.
I had to change Each() to foreach because of compilation errors and made the whole class generic.
public class AllInterfacesConvention<T> : IRegistrationConvention
{
public void ScanTypes(TypeSet types, Registry registry)
{
// Only work on concrete types
foreach (var type in types.FindTypes(TypeClassification.Concretes | TypeClassification.Closed).Where(x => typeof(T).IsAssignableFrom(x)))
{
if(type == typeof(NotInheritedClass))
{
continue;
}
// Register against all the interfaces implemented
// by this concrete class
foreach (var #interface in type.GetInterfaces())
{
registry.For(#interface).Use(type);
}
}
}
}
if you take the code sample from the link every concrete type would be included. With my changes only concerte classes which inherit from T will be included.
in your registry you would use it like that
public class TestRegistry : Registry
{
public TestRegistry()
{
Scan(x =>
{
x.TheCallingAssembly();
x.Convention<AllInterfacesConvention<YOUR_BASE_INTERFACE>>();
});
}
}
Be aware the structuremap's GetInstance will always resolve concrete classes no matter if you previously registered them.
See here https://stackoverflow.com/a/4807950/885338
I am working on asp.net mvc 4. I am trying to implement dependeny injection using ninject and repository pattern with code first model.
IMessageRepository
public interface IMessageRepository
{
void IsMessageRead();
}
MessageRepository
public class MessageRepository:IMessageRepository
{
string id="";
public MessageRepository(string idparam)
{
id=idparam;
}
EFMsgContext context=new EFMsgContext(id);
public void IsMessageRead()
{
...
}
}
EFMsgContext
public class EFMsgContext:Dbcontext
{
public EFMsgContext(string id):base("MyContext")
{
//based on id i will construct a connection string from my database.
}
....
}
my controller
public class MYController:Controller
{
private IMessageRepository repo;
public MYController(IMessageRepository repoparam)
{
repo=repoparam;
}
public ActionResult Index()
{
repo.IsMessageRead();
}
}
and i am using Ninject for dependency injection i bind my interface with concrete class like,
ninjectKernel.Bind<IMessageRepository>().To<MessageRepository>();
here how could i pass constructor parameters to the binding and is there any way to write the logic for buidling connection string inside the ninjectcontrollerfactory. please guide me.
You have to use the WithConstructorArgument extension method
ninjectKernel.Bind<IMessageRepository>().To<MessageRepository>().WithConstructorArgument("idparam", value);
You can even pass a Func as a second argument.
ninjectKernel.Bind<IMessageRepository>().To<MessageRepository>()
.WithConstructorArgument("idparam", (c) => {
// read from somewhere and return
});
I have this interface:
public interface IUserProfileService
{
// stuff
}
Implemented by:
public class UserProfileService : IUserProfileService
{
private readonly string m_userName;
public UserProfileService(string userName)
{
m_userName = userName;
}
}
I need this injected into a controller like this:
public class ProfilesController : BaseController
{
private readonly IUserProfileService m_profileService;
public ProfilesController(IUserProfileService profileService)
{
m_profileService = profileService;
}
}
I don't know how I can register this interface and its implementation into Ninject container so that userName param is passed in when the Ninject inits an instance of this service.
Any ideas how I can achieve this?
The technical ninject answer is to use constructor arguments like so:
Bind<IUserProfileService>().To<UserProfileService>().WithConstructorArgument("userName", "karl");
Of course you need to figure out where "karl" comes from. It really depends on your app. Maybe its a web app and it's on the HttpContex? I don't know. If it gets rather complicated then you might want to write a IProvider rather than doing a regular binding.
One alternative is to inject a factory and create your dependency using Create(string userName).
public class UserProfileServiceFactory
{
public IUserProfileService Create(string userName)
{
return new UserProfileService(userName);
}
}
It might seem off to have to create another class but the benefits mostly comes when UserProfileService takes in additional dependencies.
The trick is to not inject the username in that class. You call this class a service so it would probably work transparantly with multiple users. I see two solutions:
Inject an abstraction into the service that represents the current user:
public class UserProfileService : IUserProfileService
{
private readonly IPrincipal currentUser;
public UserProfileService(IPrincipal currentUser)
{
this.currentUser = currentUser;
}
void IUserProfileService.SomeOperation()
{
var user = this.currentUser;
// Do some nice stuff with user
}
}
Create an implementation that is specific to the technology you are working with, for instance:
public class AspNetUserProfileService : IUserProfileService
{
public AspNetUserProfileService()
{
}
void IUserProfileService.SomeOperation()
{
var user = this.CurrentUser;
// Do some nice stuff with user
}
private IPrincipal CurrentUser
{
get { return HttpContext.Current.User; }
}
}
If you can, go with option one.