I am trying to register a cross-AppDomain proxy with Autofac.
The concrete type represented by the proxy implements the interface IServiceHost. Thus, the proxy should also, in order to allow calls to the proxy using that interface to work.
I try to register the proxy with Autofac, by doing:
void Initialize(IServiceHost host)
{
Host = host;
var builder = new ContainerBuilder();
builder.RegisterInstance(host)
.As<IServiceHost>()
.SingleInstance();
Scope = builder.Build();
}
However, on the builder.Build() call, I get:
ArgumentException
The type 'System.MarshalByRefObject' is not assignable to service 'Treadmarks.Core.ServiceBase.IServiceHost'.
However, host is definitely an IServiceHost, since it isn't null and it comes from a strongly typed method argument.
Can anyone explain how I can register the proxy properly?
You should be able to use a lambda with the .Register() method, rather than .RegisterInstance(), to work around this.
Related
I have a service called ServiceConfiguration which has a non-default ctor. I'm trying to register it through Autofac with a factory method:
builder.Register(c=>LoadConfiguration())
.As<ServiceConfiguration>();
And here is the simple LoadConfiguration method:
private ServiceConfiguration LoadConfiguration() {
const string fileName = "app.json";
var json = File.ReadAllText(fileName, Encoding.UTF8);
var model = JsonConvert.DeserializeObject<ServiceConfiguration>(json);
return model;
}
I expect Autofac to call the LoadConfiguration when I asked to resolve ServiceConfiguration. But it seems it's trying to call a ctor on ServiceConfiguration. E.g. calling this line:
var c = container.Resolve<ServiceConfiguration>();
causes this error:
Autofac.Core.DependencyResolutionException: 'An error occurred during
the activation of a particular registration. See the inner exception
for details. Registration: Activator = ServiceConfiguration
(ReflectionActivator), Services = [ServiceConfiguration], Lifetime =
Autofac.Core.Lifetime.CurrentScopeLifetime, Sharing = Shared,
Ownership = OwnedByLifetimeScope'
and the InnerException is:
DependencyResolutionException: None of the constructors found with
'Autofac.Core.Activators.Reflection.DefaultConstructorFinder' on type
'ServiceConfiguration' can be invoked with the available services and
parameters:
Cannot resolve parameter 'JobsConfiguration jobs' of constructor 'Void .ctor(JobsConfiguration)'.
Can you find out what I'm missing?
UPDATE:
I'm not missing a registration of JobsConfiguration. Actually it's not a registrable type and I don't want to register it. I don't want to ctor get called at all (the service is getting build from a json file), instead whenever somebody asked for ServiceConfiguration I want Autofac to call LoadConfiguration() and use it's returned value.
UPDATE2:
After a while, it seems extracting an interface from ServiceConfiguration - say IServiceConfiguration - and registering/resolving the interface works just fine. But I cannot figure out why! I mean this:
builder.Register(c=>LoadConfiguration())
.As<IServiceConfiguration>();
var c = container.Resolve<IServiceConfiguration>();
works. But the concrete version not. So why? What's the difference?
You should strive separating the loading of configuration files from Object Composition. This means that it's best not to load the configuration when Resolve is called. Changing this is trivial:
ServiceConfiguration configuration = LoadConfiguration();
builder.RegisterInstance(configuration);
That said, your given registration should work:
builder.Register(c => LoadConfiguration())
.As<ServiceConfiguration>();
Which is identical to:
builder.Register(c => LoadConfiguration());
With this registration, Autofac will not Auto-Wire the ServiceConfiguration constructor, but will leave that to the supplied delegate. There might be something going on that your post is not showing.
I used the following MCVE, using Autofav 4.8.1, to verify that this works:
class ServiceConfiguration
{
public ServiceConfiguration(int a, double b) => Console.WriteLine("ctor called.");
}
static ServiceConfiguration LoadConfiguration() => new ServiceConfiguration(2, 6);
static void Main(string[] args)
{
var builder = new ContainerBuilder();
builder.Register(_ => LoadConfiguration()).As<ServiceConfiguration>();
builder.Build().Resolve<ServiceConfiguration>();
}
Last note: Make sure that ServiceConfiguration is not an application-wide configuration class that is injected into many consumers. To understand what's wrong with application-wide configuration classes, please read this Q/A.
I have an interface IMyInterface and I am registering a Moq object for unit testing like this
var myMockObject = new Mock<IMyInterface>();
myMockObject.Setup(a => a.MyMethod(It.IsAny<string>()))
.Returns(new MyResult()
{
Props1 = "Testing123",
}).Callback(() =>
{
});
builder.RegisterInstance(myMockObject).As<IMyInterface>();
var test = container.Resolve<IMyInterface>();
But I am always getting the following error:
Autofac.Core.Registration.ComponentNotRegisteredException: 'The
requested service 'IMyInterface' has not been registered. To avoid
this exception, either register a component to provide the service,
check for service registration using IsRegistered(), or use the
ResolveOptional() method to resolve an optional dependency.'
One thing to note is that I am accessing the AutoFac builder inside a static class. I have made sure that the autofac builder instance is only created once.
UPDATE it looks like I have to call builder.Build() after registering the instance. I guess all instances and types have to be registered and after that you call Build(). So it's not really possible to register more instances after that.
You are not building your Autofac container after registering.
builder.RegisterInstance(myMockObject).As<IMyInterface>();
// Create the DI container
var container = builder.Build();
var test = container.Resolve<IMyInterface>();
I have problem with Simple Injector in my Web Api project. I user default AccountController generated by VS.
public AccountController(ApplicationUserManager userManager,
ISecureDataFormat<AuthenticationTicket> accessTokenFormat)
In my configuration file I register:
var container = new Container();
// This is an extension method from the integration package.
container.RegisterWebApiFilterProvider(config);
container.RegisterWebApiControllers(config);
container.Register<IInitializeService, InitializeService>();
container.Register<IFolderRepository, FolderRepository>();
container.Register<IUserRepository, UserRepository>();
container.Register<ILogger, Logger>();
//Authentication Wrap
container.Register<IUserStore<User, Guid>, ApplicationUserStore>();
container.Register<IDataSerializer<AuthenticationTicket>, TicketSerializer>();
container.Register<ISecureDataFormat<AuthenticationTicket>,
SecureDataFormat<AuthenticationTicket>>();
container.Register<IDataProtector>(
() => new DpapiDataProtectionProvider().Create("ASP.NET Identity"));
container.Verify();
// 4. Register the container as MVC3 IDependencyResolver.
DependencyResolver.SetResolver(new SimpleInjectorWebApiDependencyResolver(container));
config.DependencyResolver = new SimpleInjectorWebApiDependencyResolver(container);
I though that Simple Injector will be smart enough to handle all build in dependences responsible for default identity and i wont need to register them manually, but I'm getting exceptions if I wont register them.
Still getting an exception:
The constructor of type SecureDataFormat contains the parameter of type ITextEncoder with name 'encoder' that is not registered. Please ensure ITextEncoder is registered in the container, or change the constructor of SecureDataFormat.
Is there any way to handle that automatically?
I implemented a Web Api and I wrote this code.
This works for me
container.RegisterWebApiRequest<ISecureDataFormat<AuthenticationTicket>, SecureDataFormat<AuthenticationTicket>>();
container.RegisterWebApiRequest<ITextEncoder, Base64UrlTextEncoder>();
container.RegisterWebApiRequest<IDataSerializer<AuthenticationTicket>, TicketSerializer>();
container.RegisterWebApiRequest<IDataProtector>(() => new Microsoft.Owin.Security.DataProtection.DpapiDataProtectionProvider().Create("ASP.NET Identity"));
How is the container supposed to know which implementation of ITextEncoder you want to use in the constructor of SecureDataFormat?
You have to tell it which one to use. I think the rules basically go something like this:
if an interface is required (by a constructor) then it needs to know which implementation to use. If a concrete class is required it will automatically build an instance of that class (assuming it can resolve all the types that class needs).
As your SecureDataForms needs an interface you have to register one, otherwise its only option would be to 'guess' at which implementation you want and this could then go wrong silently if more than one implementation existed.
I just came up against this issue. I'm using ninject but you'll get the idea. Here is my binding:
kernel.Bind<ITextEncoder>().To<Base64UrlTextEncoder>();
According to the source, the only thing I ever see being used to new up an instance of SecureDataFormat is Base64UrlTextEncoder. So it seemed like a safe bet to use, but it's certainly not clear to me at first glance how to appropriately use this constructor overload.
I have a WCF RESTful service that I want to integration test so need to create an instance of the service locally within the test with a reference to a client channel that I can call. I can do this, however the code I'm using will only call the Services default parameterless constructor as below
_serviceHost = new WebServiceHost(typeof(UserService), baseAddress);
var binding = new WebHttpBinding();
_serviceHost.AddServiceEndpoint(typeof(Interface.IUserService), binding, address.Uri);
_serviceHost.Open();
In my UserService class, I want to inject a dependency into it for the data repository, as so
public UserService(IUserDataRepository userRepository)
{
_userRepository = userRepository;
}
How can I adapt the first lot of code so that I can create and self host my WCF REST service with an IDataRepository object that I create (Mock) in the test class?
Well, I think you can use the same approach as you have for production environment. I might be wrong but you must already have your custom ServiceHost and ServiceHostFactory. If not please take a look at this article Using Instance Provider and ServiceHostFactory to Construct the Service. You want to read through steps steps 1-3. You will need to derive from WebServiceHost to implement your own one. Then your code will look like that:
_serviceHost = new YourCustomServiceHost(typeof(UserService), baseAddress);
Hope it helps!
I'm using a UnityContainer.
I want to register in it AuthService and TokenManager.
AuthService has TokenManager as a private memeber.
TokenManager has one ctor: TokenManager(string name, string pass)
I get these strings from the UI at runtime.
Unity require to register ctor parameters in a config file.
I have thought
to create a ctor: AuthService(TokenManager mgr)
But then how do I add an object (non-primitive) to the <unity> node in the config file?
How can I still use Unity with runtime parameter to TokenManager ctor?
My idea:
AuthService will have two ctor - parameterless and AuthService(bool initFromContainer)
In test harness I will call new AuthService(false) and then override the TokenManager
using AuthService_Accessor
Define a factory for TokenManager and inject the factory into AuthService. Make the factory accept the parameters for username and password.
Injecting a factory works quite well whenever you need to incorporate runtime parameters. But don't get carried away with that pattern or you might bump into factory overload.