Unable to resolve service for type 'System.String' while attempting to activate in .net core - asp.net-core

I have a factory class and it has a constructor where dependency injection is implemented. When trying to register the factory method in program.cs file I get the below error when running the application. "Unable to resolve service for type 'System.String' while attempting to activate 'Factory".
public class Factory : IFactory
{
private readonly A _a;
private readonly string _test;
public Factory(A a, string sample)
{
_a= a;
_test= string.IsNullOrEmpty(sample) ? string.Empty : Path.GetFullPath(sample);
}
private string Create(long id)
{
var b = _test.make(id);
return b;
}
}
In program.cs file how can we register this string element _test? Can anyone help!

It is because your Factory constructor is not parameter-less, and when the service provider tries to instantiate the Factory, it has no value to pass for the "sample" variable.
There are two possible solutions to this:
1- Changing the design of your factory, and passing the "sample" as a variable to Create method instead of the constructor.
OR
2- Registering the factory like this:
services.AddSingleton(s => new Factory(s.GetService<A>(), "desired string"));
Btw, I don't know what is the use case that you have for implementing this factory class, but it doesn't seem the right way of implementing it. I suggest you take a look at this beforehand:
Factory Design Pattern

Related

In ASP.NET core, inject a service with constructor parameters [duplicate]

Having the following service constructor
public class Service : IService
{
public Service(IOtherService service1, IAnotherOne service2, string arg)
{
}
}
What are the choices of passing the parameters using .NET Core IOC mechanism
services.AddSingleton<IOtherService , OtherService>();
services.AddSingleton<IAnotherOne , AnotherOne>();
services.AddSingleton<IService>(x =>
new Service(
services.BuildServiceProvider().GetService<IOtherService>(),
services.BuildServiceProvider().GetService<IAnotherOne >(),
""));
Is there any other way ?
The expression parameter (x in this case) of the factory delegate is an IServiceProvider.
Use that to resolve the dependencies:
_serviceCollection.AddSingleton<IService>(x =>
new Service(x.GetRequiredService<IOtherService>(),
x.GetRequiredService<IAnotherOne>(),
""));
The factory delegate is a delayed invocation. Whenever the type is to be resolved, it will pass the completed provider as the delegate parameter.
The recommended way to achieve this is to use the Options pattern - note that this applies to any .NET Core/5 application, not just ASP.NET Core. But there are use cases where it's impractical (e.g. when parameters are only known at runtime, not at startup/compile-time) or you need to dynamically replace a dependency.
It's very useful when you need to replace a single dependency (be it a string, integer or another type of dependency) or when using a 3rd-party library which accepts only string/integer parameters and you require runtime parameters.
You could try ActivatorUtilities.CreateInstance<T>(IServiceProvider, Object[]) as a shortcut rather than resolving every single dependency manually:
_serviceCollection.AddSingleton<IService>(x =>
ActivatorUtilities.CreateInstance<Service>(x, "");
);
The parameters to pass to your service's constructor (the object[] parameter to CreateInstance<T>/CreateInstance) allows you to specify parameters that should be injected directly, as opposed to resolved from the service provider. They are applied from left to right as they appear (i.e. first string will be replaced with the first string-typed parameter of the type to be instantiated).
ActivatorUtilities.CreateInstance<Service> is used in many places to resolve service and replace one of the default registrations for this single activation.
For example, if you have a class named MyService, and it has IOtherService, ILogger<MyService> as dependencies and you want to resolve the service but replace the default service of IOtherService (say it's OtherServiceA) with OtherServiceB, you could do something like:
myService = ActivatorUtilities.CreateInstance<Service>(serviceProvider,
new OtherServiceB());
Then the first parameter of IOtherService will get OtherServiceB injected, rather than OtherServiceA - but the remaining parameters will come from the service provider.
This is helpful when you have many dependencies and want just to treat a single one specially (i.e. replace a database-specific provider with a value configured during the request or for a specific user, something you only know at runtime and/or during a request - not when the application is built/started).
If performance is a concern, you can use ActivatorUtilities.CreateFactory(Type, Type[]) to create a factory method instead. GitHub reference and benchmark.
This is useful when the type is resolved very frequently (such as in SignalR and other high request scenarios). Basically, you'd create an ObjectFactory via
var myServiceFactory = ActivatorUtilities.CreateFactory(typeof(MyService), new Type[] { typeof(IOtherService), });
then cache it (as a variable etc.) and invoke it where needed:
MyService myService = myServiceFactory(serviceProvider, myServiceOrParameterTypeToReplace);
This all works perfectly with primitive types too - here's an example I tested with:
class Program
{
static void Main(string[] args)
{
var services = new ServiceCollection();
services.AddTransient<HelloWorldService>();
services.AddTransient(p => p.ResolveWith<DemoService>("Tseng", "Stackoverflow"));
var provider = services.BuildServiceProvider();
var demoService = provider.GetRequiredService<DemoService>();
Console.WriteLine($"Output: {demoService.HelloWorld()}");
Console.ReadKey();
}
}
public class DemoService
{
private readonly HelloWorldService helloWorldService;
private readonly string firstname;
private readonly string lastname;
public DemoService(HelloWorldService helloWorldService, string firstname, string lastname)
{
this.helloWorldService = helloWorldService ?? throw new ArgumentNullException(nameof(helloWorldService));
this.firstname = firstname ?? throw new ArgumentNullException(nameof(firstname));
this.lastname = lastname ?? throw new ArgumentNullException(nameof(lastname));
}
public string HelloWorld()
{
return this.helloWorldService.Hello(firstname, lastname);
}
}
public class HelloWorldService
{
public string Hello(string name) => $"Hello {name}";
public string Hello(string firstname, string lastname) => $"Hello {firstname} {lastname}";
}
// Just a helper method to shorten code registration code
static class ServiceProviderExtensions
{
public static T ResolveWith<T>(this IServiceProvider provider, params object[] parameters) where T : class =>
ActivatorUtilities.CreateInstance<T>(provider, parameters);
}
Prints
Output: Hello Tseng Stackoverflow
If you feel uncomfortable with newing the service, you could use the Parameter Object pattern.
So extract the string parameter into its own type
public class ServiceArgs
{
public string Arg1 {get; set;}
}
And the constructor will now look like
public Service(IOtherService service1,
IAnotherOne service2,
ServiceArgs args)
{
}
And the setup
_serviceCollection.AddSingleton<ServiceArgs>(_ => new ServiceArgs { Arg1 = ""; });
_serviceCollection.AddSingleton<IOtherService , OtherService>();
_serviceCollection.AddSingleton<IAnotherOne , AnotherOne>();
_serviceCollection.AddSingleton<IService, Service>();
The first benefit is if you need to change the Service constructor and add new services to it, then you don't have to change the new Service(... calls. Another benefit is the setup is a bit cleaner.
For a constructor with a single parameter or two, this might be too much though.
You can inject dependencies with this process also
_serviceCollection.AddSingleton<IOtherService , OtherService>();
_serviceCollection.AddSingleton<IAnotherOne , AnotherOne>();
_serviceCollection.AddSingleton<IService>(x=>new Service( x.GetService<IOtherService>(), x.GetService<IAnotherOne >(), "" ));

Registering a BackgroundService from a Type

Is there any way to register a background service from a type?
With the code below, if I remove the cast to BackgroundService, the code won't compile.
As it stands below, then I only get a single one of the services from the array registered.
If I change it to IHostedService, then I receive this exception.
System.ArgumentException: Implementation type cannot be 'Microsoft.Extensions.Hosting.IHostedService' because it is indistinguishable from other services registered for 'Microsoft.Extensions.Hosting.IHostedService'. (Parameter 'descriptor')
My code:
.ConfigureServices((hostContext, services) =>
{
Type[] backgroundServices = GetBackgroundServices(assemblies).ToArray();
foreach (var #type in backgroundServices)
services.AddHostedService((ihs) => (BackgroundService)ihs.GetRequiredService(#type));
})
Thanks very much
The extension AddHostedService simply does this:
services.AddTransient<IHostedService, THostedService>();
Where THostedService is a class that implements IHostedService.
So, if you wanted to inject a hosted service by type, you would simply do:
services.AddTransient(typeof(IHostedService), typeof(MyBackgroundService));
MyBackgroundService in this case would need to be set up as either this:
public class MyBackgroundService : IHostedService { ... }
Or this:
public class MyBackgroundService : BackgroundService { ... }
BackgroundService implements IHostedService... so both of theses cases would work with the above method.

Getting 'Context is not constructible. Add a default constructor or provide an implementation of IDbContextFactory."

I am getting this error when I try to use code first migrations.
My context has a constructor with the connection name.
public class VeraContext : DbContext, IDbContext
{
public VeraContext(string NameOrConnectionStringName = "VeraDB")
: base(NameOrConnectionStringName)
{
}
public IDbSet<User> Users { get; set; }
public IDbSet<Product> Products { get; set; }
public IDbSet<IntCat> IntCats { get; set; }
}
This connection name is injected with ninject when the project runs, I have also specified it as a default as in the above code but this did not help.
kernel.Bind<IDbContext>()
.To<VeraContext>()
.WithConstructorArgument("NameOrConnectionStringName", "VeraDB");
When I try to add migrations with "Enable-Migrations" is throws up the error:
The target context 'VeraData.EF.Infrastructure.VeraContext' is not
constructible. Add a default constructor or provide an implementation
of IDbContextFactory.
If I remove the constructor from VeraContext it will work but creates another database with VeraData.EF.Infrastructure.VeraContext as its name.
I presume that ninject only passes the connection string when the project runs and not when I use code first migrations. Anyway I can inject/provide a default for the connection name when using code first migrations ?
Essentially you need a default ctor (that's the error) - but just implementing it would lead to problems.
You'd have to implement the IDbContextFactory for the results to be consistent (or your migration from code won't work etc.).
Migrations actually call your default constructor to make a
connection. So you're other ctor won't matter much.
Here is the basic factory...
public class MyContextFactory : IDbContextFactory<MyContext>
{
public MyContext Create()
{
return new MyDBContext("YourConnectionName");
}
}
You should combine that with injection, to inject and construct your DbContext as you wish.
If you don't want to spend time looking into the IDbContextFactory option, and to get things working create a default constructor and hard-code the name of the connection string when calling the base DbContext:
public class CustomContext : DbContext
{
public CustomContext() :base("name=Entities") {}
}
SRC: http://www.appetere.com/Blogs/SteveM/April-2012/Entity-Framework-Code-First-Migrations
To complement #nccsbim071 answer, I have to add one more thing... this option doesn't like constructor with default parameters... for instance:
public MyContext(bool paramABC = false) : base("name=Entities") {...}
instead you have to create a non-parameter (default) constructor and the parameter-constructor like old fashion way.
public MyContext() :base("name=Entities") {...}
public MyContext(bool paramABC) : this() {...}
NOTE:
Entities in this case means the connection string name... By convention, the name of the context is the same as the connection string name and since MyContext is not the same as Entities, it's necessary specify it manually.
In my situation I wanted to use the default connection factory, instead of explicitly providing one. Somewhere inside EF6 it'll try to lookup the factory, but it fails with this exception message. Stepping through the EF6 code, I found that Glimpse.Ado was wrapping the connection factory, which made the lookup fail to find a match.

using custom types in a WCF service

I'm new in WCF and now stuck in something about using custom types in WCF service.
I have two classes Class1 and Class2 in TestClass project
public Class1: ArrayList{
public string street;
}
public Class2{
public string name;
public string address;
}
My WCF service TestService include function DoSomething using two above classes
public string DoSomething(Class1 c1){
return c1.street;
}
And when try to call this function
Class1 c1 = new Class1();
Class2 c2 = new Class2();
c1.Add(c2);
ServiceClient1.Dosomething(c1);
I get the Exception
There was an error while trying to serialize parameter http://tempuri.org/:c1. The
InnerException message was 'Type 'WebApplication1.Class2' with data contract name
'Class2:http://schemas.datacontract.org/2004/07/WebApplication1' is not expected. Add
any types not known statically to the list of known types - for example, by using the
KnownTypeAttribute attribute or by adding them to the list of known types passed to
DataContractSerializer.'. Please see InnerException for more details.
Can anyone tell me how to add DataContract for a class defined outside the WCF service, and how to solve this problem.
Thanks a lot!
Add the lines below to your service interface declaration (add them just below the ServiceContract attribute):
[ServiceKnownType(typeof(Class1))]
[ServiceKnownType(typeof(Class2))]
alternatively, and this is the recommended approach, define your set of DTO objects exported by the service and decorate them with [DataContract] and [DataMember] attributes.

Dozer BeanFactory: How to implement it?

I have looked at the Dozer's FAQs and docs, including the SourceForge forum, but I didn't see any good tutorial or even a simple example on how to implement a custom BeanFactory.
Everyone says, "Just implement a BeanFactory". How exactly do you implement it?
I've Googled and all I see are just jars and sources of jars.
Here is one of my BeanFactories, I hope it helps to explain the common pattern:
public class LineBeanFactory implements BeanFactory {
#Override
public Object createBean(final Object source, final Class<?> sourceClass, final String targetBeanId) {
final LineDto dto = (LineDto) source;
return new Line(dto.getCode(), dto.getElectrified(), dto.getName());
}
}
And the corresponding XML mapping:
<mapping>
<class-a bean-factory="com.floyd.nav.web.ws.mapping.dozer.LineBeanFactory">com.floyd.nav.core.model.Line</class-a>
<class-b>com.floyd.nav.web.contract.dto.LineDto</class-b>
</mapping>
This way I declare that when a new instance of Line is needed then it should create it with my BeanFactory. Here is a unit test, that can explain it:
#Test
public void Line_is_created_with_three_arg_constructor_from_LineDto() {
final LineDto dto = createTransientLineDto();
final Line line = (Line) this.lineBeanFactory.createBean(dto, LineDto.class, null);
assertEquals(dto.getCode(), line.getCode());
assertEquals(dto.getElectrified(), line.isElectrified());
assertEquals(dto.getName(), line.getName());
}
So Object source is the source bean that is mapped, Class sourceClass is the class of the source bean (I'm ignoring it, 'cause it will always be a LineDto instance). String targetBeanId is the ID of the destination bean (too ignored).
A custom bean factory is a class that has a method that creates a bean. There are two "flavours"
a) static create method
SomeBean x = SomeBeanFactory.createSomeBean();
b) instance create method
SomeBeanFactory sbf = new SomeBeanFactory();
SomeBean x = sbf.createSomeBean();
You would create a bean factory if creating and setting up your bean requires some tricky logic, like for example initial value of certain properties depend on external configuration file. A bean factory class allows you to centralize "knowledge" about how to create such a tricky bean. Other classes just call create method without worying how to correctly create such bean.
Here is an actual implementation. Obviously it does not make a lot of sense, since Dozer would do the same without the BeanFactory, but instead of just returning an object, you could initialized it somehow differently.
public class ComponentBeanFactory implements BeanFactory {
#Override
public Object createBean(Object source, Class<?> sourceClass,
String targetBeanId) {
return new ComponentDto();
}
}
Why do you need a BeanFactory anyways? Maybe that would help understanding your question.