ASPNET CORE Dependency Injection in an attribute class - c#

I am trying to develop a DisplayName Attribute which has an interface for localization service, which is already registered at startup and working if injected in a constructor.
How can I get the localization service interface to be instantiated since I cant use a construction injection?
This is my code
public class MyDisplayNameAttribute : System.ComponentModel.DisplayNameAttribute
{
private string _resourceValue = string.Empty;
private ILocalizationService _localizationService;
public MyDisplayNameAttribute(string resourceKey)
: base(resourceKey)
{
ResourceKey = resourceKey;
}
public string ResourceKey { get; set; }
public override string DisplayName
{
get
{
_resourceValue = _localizationService.GetLocaleString(ResourceKey);
return _resourceValue;
}
}
public string Name
{
get { return nameof(MyDisplayNameAttribute); }
}
}
Thanks

I hope you could solve the problem, this is a very simple solution but as you knew it's an anti-pattern :
public class LocalizedDisplayNameAttribute : DisplayNameAttribute
{
public LocalizedDisplayNameAttribute(string Name) : base(Name)
{
}
public override string DisplayName
{
get
{
var _localizationService= new HttpContextAccessor().HttpContext.RequestServices.GetService<ILocalizationService>();
return _localizationService.Get(base.DisplayNameValue).Result;
}
}
}
I Hope it helps others at least ;)

Dependency injection is working with invertion of control (https://learn.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-2.2). So framework controls your app and when instantiating your clsses injects dependencies requested via constructor.
Refer also here How to create a class without constructor parameter which has dependency injection
So I suspect that it is not possible to inject dependency without using constructor.
May be if you describe you intention there may be another good solution.

Related

How to get object of derived class of a parent class which passed in constructor through dependency injection

I have a user class hierarchy a follows:
public class BaseUser
{
public virtual UserTask()
{
// Some Code
}
}
public class SubUser1 : BaseUser
{
public override UserTask()
{
// Some Code
}
}
public class SubUser2 : SubUser1
{
public override UserTask()
{
// Some Code
}
}
And there is a class with constructor using dependency injection as follows:
public class UserManagement
{
public UserManagement(BaseUser user)
{
// Some code
}
}
I am working on Asp.Net Web API, in which a controller use this class UserManagement.
My problem is how to get object of SubUser1 and SubUser2 in UserManagement constructor.
I am new to Dependency Injection.
Please suggest any solution or article which guide me to achieve this.
Any help would be appreciated.

Accessing settings from appsettings.json from class library in Core 2.0

I've read a dozen questions here on SO and at least 4 blog posts but I cannot get this to work in a VS2017 solution with multiple class library projects. However, I can get it to work with a solution with a web application and one class library, albeit with a different pattern than the one I've found in the documentation and here on SO.
My solution contains 5 projects a WebApplication, Testing, Infrastructure, Services, Domain (the latter three are class libraries).
In the infrastructure project I have created a class called EmailConfigurationSettings and registered it in the StartUp class of the WebApp.
This class is in class library:
public class EmailConfigurationSettings
{
public string Provider { get; set; }
public string Username { get; set; }
public string Password { get; set; }
}
This is in StartUp.cs in WebApp:
services.Configure<EmailConfigurationSettings>(Configuration.GetSection("EmailConfigurationSettings"));
services.AddOptions();
appsettings.json
"EmailConfigurationSettings": {
"Provider": "gmail",
"Username": "user#gmail.com",
"Password": "mypassword"
}
I need the settings in the Services project. But for now I am just trying to ensure I can actually retrieve them. The code below follows all the code samples I found but generates:
public class LoadEmailSettingsFromAppSettings
{
private readonly IOptions<EmailConfigurationSettings> _emailSettings;
public LoadEmailSettingsFromAppSettings(IOptions<EmailConfigurationSettings> emailSettings)
{
_emailSettings = emailSettings;
Message = "Our provider is " + _emailSettings.Value.Provider;
}
public string Message { get; set; }
}
_emailSettings is always null
So I tried testing it in the TestProject:
IOptions<EmailConfigurationSettings> someOptions = Options.Create<EmailConfigurationSettings>(new EmailConfigurationSettings());
Well, that's null too.
In the other solution, the one with the WebApp and one class library,
using a slightly different pattern I found on one of the blogs I can actually retrieve the values from appsettings.json:
public class AuthMessageSender : IEmailSender, ISmsSender
{
public AuthMessageSender(IOptions<EmailConfig> emailSettings)
{
_emailSettings = emailSettings.Value;
}
public EmailConfig _emailSettings { get; }
public Task SendEmailAsync(string email, string subject, string message)
{
Execute(email, subject, message).Wait();
return Task.FromResult(0);
}
Please note the IOptions class was different with 9 properties but constructed the same way as the pattern above.
But using this pattern does not work in the multiple class library project. How can I understand how to get this to work in a multiple class library scenario?
Why they abandoned the ConfigurationManager I don't know, it was far easier.
In microservices you can simple do a bind to a new object that matches the json definition. So you would do.
var emailConfig = new EmailConfigurationSettings();
Configuration.GetSection("EmailConfigurationSettings").Bind(emailConfig);
services.AddSingleton(emailConfig);
Once you do this, all you have to do is request a copy of EmailConfigurationSettings in your service layers constructor. This will give you the dependency injected singleton of that object.
I would set a breakpoint on the "bind" and make sure that email config is populated.
Here is an interesting answer about class library : Class library.
In this part of your code:
private readonly IOptions<EmailConfigurationSettings> _emailSettings;
public LoadEmailSettingsFromAppSettings(IOptions<EmailConfigurationSettings> emailSettings)
{
_emailSettings = emailSettings;
the dependency injection don't work because you are in a class library so you should keep it that way.
Somewhere in your webapp you construct LoadEmailSettingsFromAppSettings
public class SomeClass
{
public SomeClass(IOptions<EmailConfigurationSettings> emailSettings) // dependency injection works in your webapp
{
var loadEmail = new LoadEmailSettingsFromAppSettings(emailSettings); // send EmailSettings to your other class in your class library
//(...)
}
}
And the private readonly should be:
public IOptions<EmailConfigurationSettings> EmailSettings {get; private set;}
readonly vs get/set properties
I hope is clear and helpful

Ninject Factory Extension

I'm having a little trouble wrapping my head around the Ninject Factory Extension.
I have the following class structure
public class Resource
{
public IResourceLoader ResourceLoader {get;set;}
public Resource(IResourceLoader ResourceLoader)
{
this.ResourceLoader = ResourceLoader ;
}
}
public class Banner : Resource
{
public Banner([Named("pngLoader")] IResourceLoader ResourceLoader)
:base(ResourceLoader)
{ }
}
public class MetaData : Resource
{
public MetaData ([Named("xmlLoader") IResourceLoader ResourceLoader)
:base(ResourceLoader)
{ }
}
interface IResourceLoader
{
object resource {get;}
}
public class XMLLoader : IResourceLoader
{
public resource { return "this was sent by xml loader"; }
}
public class PNGLoader : IResourceLoader
{
public resource { return "this was sent by png loader"; }
}
I'm trying to implement convention based filtering based on the Named attribute as show here. So I implemented the following interface.
interface IResourceLoaderFactory
{
IResourceLoader GetxmlLoader();
IResourceLoader GetpngLoader()
}
And then my bindings in the dependency resolver look like
kernel.Bind<IResourceLoader>().To<XMLLoader>().NamedLikeFactoryMethod((IResourceLoaderFactory f) => f.GetxmlLoader());
kernel.Bind<IResourceLoader>().To<PNGLoader>().NamedLikeFactoryMethod((IResourceLoaderFactory f) => f.GetpngLoader());
Assuming the above is correct, I don't know how to proceed to have it so that Ninject gives Banner or MetaData the correct IResourceLoader based on the [Named] in the constructor that it passes it to the base constructor.
I'm using all of this in an mvc 5 application like
public class HomeController
{
public ActionResult Index(/* do banners and meta need to be asked for here? */)
{
/* or do I need to instantiate them here/? */
Banner banner = new Banner(/* what to put here? */);
Meta meta = new Meta(/* what to put here? */);
...
}
}
Thanks
Let me try to answer your question, i'm not a 100% sure i've understand your question correctly, so please give me feedback if i haven't.
Now, your basic problem is that you want to inject an IResourceLoader - but depending on what you inject it into, it should either be an XMLLoader or a PNGLoader.
You've correctly identified named bindings as one possible solution for choosing the appropriate IResourceLoader.
However, you don't need to combine NamedLikeFactory and [Named]-Attribute pattern to achieve what you want, one of those is enough, and here the [Named]-Attribute is probably the better alternative of the two (there is a third which i'll get to later).
So here's what you do:
public const string XmlLoaderName = "XmlLoader";
public const string PngLoaderName = "PngLoader";
Bind<IResourceLoader>().To<XMLLoader>()
.Named(XmlLoaderName);
Bind<IResourceLoader>().To<PNGLoader>()
.Named(PngLoaderName);
And then you specify the appropriate type in the ctor (as you did):
public class Banner : Resource
{
public Banner([Named(pngLoaderName)] IResourceLoader ResourceLoader)
:base(ResourceLoader)
{ }
}
public class MetaData : Resource
{
public MetaData ([Named(xmlLoaderName) IResourceLoader ResourceLoader)
:base(ResourceLoader)
{ }
}
and that's basically it!
now to use it in your controller all you've got to do is:
public class HomeController
{
public HomeController(Banner baner, MetaData metaData)
{
...
}
}
no need to use a factory. Except, in case you need to instantiate a Banner orMetaData instance per request, in which case you would create a factory interface:
public interface IResourceFactory
{
Banner CreateBanner();
MetaData CreateMetaData();
}
which is bound like:
Bind<IResourceFactory>().ToFactory();
// ToFactory is an extension method from Ninject.Extensions.Factory
which will be used like:
public class HomeController
{
private readonly IResourceFactory resourceFactory;
public HomeController(IResourceFactory resourceFactory)
{
this.resourceFactory = resourceFactory;
}
public ActionResult Index()
{
var banner = this.resourceFactory.CreateBanner();
....
}
}
Alternative for Named binding: You could also use a conditional binding like:
Bind<IResourceLoader>().To<XMLLoader>()
.WhenInjectedInto<Banner>();
and corresponding Banner ctor:
public Banner(IResourceLoader resourceLoader)
{
...
}
This alternative can make sense if there's a very limited set of classes which get a ResourceLoader injected. Or if you can't add an [Named]-Attribute to the ctor (for example because it's a third party library...).
Another alternative altogether again would be to give Ninject more information on how to construct a type. For Example:
Bind<Banner>().ToSelf()
.WithConstructorArgument(
typeof(IResourceLoader),
ctx => ctx.Kernel.Get<XmlLoader>());

Using ServiceStack Funq IoC: how dependencies are injected?

I have WinForm application and I want to use ServiceStack dependency injection mechanism:
public class AppHost : AppHostBase
{
public AppHost()
: base("MyName", typeof(AppHost).Assembly)
{
}
public override void Configure(Container container)
{
container.RegisterAutoWiredAs<AppApplicationContext, IAppApplicationContext>();
}
}
Then in some form class use it:
public class SomeClass : AppBaseForm
{
public IAppApplicationContext AppApplicationContext { get; set; }
public SomeClass(IAppApplicationContext appApplicationContext)
{
AppApplicationContext = appApplicationContext;
}
public SomeClass()
{
}
}
But AppApplicationContext is always null. When in parameterless constructor I write:
AppApplicationContext = AppHostBase.Resolve<IAppApplicationContext>();
then every thing is OK. But is this right way to do that? I mean AppApplicationContext should not be resolved by IoC automatically? And WinForm must have parameterless constructor.
Rest of code:
private static void Main()
{
var appHost = new AppHost();
appHost.Init();
}
public interface IAppApplicationContext
{
}
public class AppApplicationContext : IAppApplicationContext
{
}
You need to call AutoWire to have the container inject the dependancies. You can use it in your WinForm app like this:
public class SomeClass : AppBaseForm
{
public IAppApplicationContext AppApplicationContext { get; set; }
public SomeClass()
{
// Tell the container to inject dependancies
HostContext.Container.AutoWire(this);
}
}
When you use a regular ServiceStack service, the AutoWire happens behind the scenes during the request pipeline when ServiceStack creates an instances of your Service.
I have created a fully working example here. Note: The demo is just a console application, not WinForms but it does shows the IoC being used outside of the ServiceStack service, and it works no differently.

How to inject something in custom validator?

I'm using CustomValidation for one entity and I want to inject Repository in it. Validation method must be static. Is there any way to inject object in static context other than service location?
Here's my metadata:
[MetadataTypeAttribute(typeof(BillPosition.BillPositionsMetadata))]
[CustomValidation(typeof(BillPositionValidator), "ValidateBillPositionsCount")]
public partial class BillPosition
{
internal sealed class BillPositionsMetadata
{
private BillPositionsMetadata() { }
public int BillId { get; set; }
}
}
Here's validator code:
public class BillValidator
{
[Inject]
public static IRepository Repository { get; set; }
public static ValidationResult ValidateBillPositionsCount(BillPosition bill, ValidationContext context)
{
ValidationResult result = ValidationResult.Success;
/* Repository wasn't injected and I get null reference exception */
var billPositions = Repository.BillPositions.Count(position => position.BillId == bill.BillId);
if (bill.BillPositions.Count == 0 && billPositions == 0)
{
result = new ValidationResult("Invalid positions count", new[] { "BillPositions" });
}
return result;
}
}
There is not any way to inject into custom validators. A Service Locator or some form of reflection could be used to either access a property or method on the instance the validator is being executed on. You can access this instance through the ValidationContext.
http://www.jaltiere.com/index.php/2010/05/04/ninject-with-mvc-and-validationattributes/
You can just call the IoC and resolve the dependency. Like I am using Unity. In these cases I would call Bootstrapper.Unity.Resolve("NameOfMyDependency")
If you are not resolving the validator from the dependency injection container, you can still resolve the repository directly using some kind of service locator:
public class BillValidator
{
static BillValidator()
{
Repository = ServiceLocator.Current.GetInstance<IRepository>();
}
public static IRepository Repository { get; set; }
}
That way you can initialize the validator using the new-keyword:
var validator = new BillValidator();
and you still get the dependency resolved in the validator.
Due to the fact that the repository gets resolve in the type initializer it will be executed only once per type in your applcation. All instances of the validator will use the same repository.
This code works when working with Unity, but should be equivalent when working with MEF or other containers.

Categories