By default, Automapper is able to use protected constructors for mapping. However, it just takes the one with most suitable parameters and uses it. How could I tell Automapper which protected constructor to use?
Related
Requiring to sometimes use dependency injection in ActioFilter or other attributes running before or after an action API or result is inevitable. However, it is carried out through passing the type to be injected to the attribute using the typeof keyword. In order to simplify the case, when having various implementations for an interface, I have found it much simpler to manually instantiate the type than using the built-in dependency injection framework. For example:
public TestAttribute: Attribute, IActionFilter {
private Type injectionType;
public TestAttribute(Type injectionType){
...
}
...
public void OnActionExecuting(ActionExecutingContext context) {
InjectedTypeInterface injectedTypInterface = (InjectedTypeInterface) Activator.CreateInstance(injectedType, arg1, arg2, ...);
...
}
}
I want to know, from the point of view of other people here, that would this approach cause problems that using the built-in dependency injection framework would not? (Injected implementation will be always Transient in this case and not Scoped or Singleton)
I don't recommend doing the route of Activator.CreateInstance, here are some reasons why to avoid it and stick with the official way:
You'd need to pass in all instances of the parameters (i.e. of the type you want to instantiate has other dependencies) to it
The instance created this way isn't tracked by the scoped container. This also means, it won't automatically get disposed (Updated note this of course will only happen if the service implements IDisposable interface) at the end of the request and instead be disposed at some indeterminable time in future, when the GC kicks in and will keep resources open for longer then intended (i.e. holding connection or file handle open for longer then intended) unless you dispose it explicitly
Like you already recognized, you can't do so with scoped and singleton instances
For your concrete examples, there are easier ways to get a specific instance from DI - aside from the official supported ways (Filters - Dependency Injection) - you can also resolve from HttpContext, assuming you have access to it in the type of filter you are using.
For ActionFilter/IActionFilter
public void OnActionExecuting(ActionExecutingContext context) {
InjectedTypeInterface injectedTypInterface = context.HttpContext
.RequestServices.GetService<InjectedTypeInterface>();
...
}
I'm using feature flags to selectively enable/disable certain aspects of my MVC4 web application in different environments. I have an interface named IConfiguration with a IsEnabled(FeatureFlag) method that provides access to these flags.
To this end, I want to disable certain MVC action methods when the feature they relate to is turned off. I have an attribute named FeatureAttribute defined like this:
// Usage: [Feature(FeatureFlag.I18N)]
public class FeatureAttribute : ActionMethodSelectorAttribute {
private IConfiguration _config;
private FeatureFlag _feature;
public FeatureAttribute(FeatureFlag feature) {
_config = DependencyResolver.Current.GetService<IConfiguration>();
_feature = feature;
}
public override bool IsValidForRequest(ControllerContext controllerContext,
MethodInfo methodInfo) {
return _config.IsEnabled(_feature);
}
}
This works, but using DependencyResolver to get an instance of IConfiguration smells funny. Is there any way I can redesign my code to avoid the Service Locator pattern?
I initially thought of using filter injection, but ActionMethodSelectorAttribute is not actually a filter, so it doesn't apply here.
Attributes are created by the .NET Framework. So you can't do Constructor injection. The only two ways to inject into Attributes is to do PropertyInjection or ServiceLocation.
PropertyInjection can be done like this:
Add a IPlanningStrategy that does the scanning with reflection for your attribute (or ActionMethodSelectorAttribute). Return immediatly if not a controller.
Foreach method that has this attribute add a IDirective that contains a reference to the MethodInfo
Add A IActivationStrategy that injects the attribute using kernel.Inject(attribute).
Best you have a look at the PropertyInjection implementation of Ninject it works exactly like this. It just needs some changes to do what you want.
To begin with two things.
I am trying to achieve an action filter that logs when and action begins and when it end
I am well aware of the .AsActionFilter() method in Autofac 3.0 BUT...
The project that this is using is based in Orchard 1.6 which is known to be compatible with autofac 2.6.xxx. We do not want to go through a potentially lengthy process of upgrading to Autofac 3.0 at this time so the .AsActionFilter() option is not available to us.
The other option is to set the filter (which extends ActionFilterAttribute) as an attribute on our base controller (from which all other inherit btw). The problem is that the filter itself has two dependencies:
A service of our own that holds information on the context
An implementation of an ILoggingService
What I cannot find is a way to inject these into the actual property at the head of the class. Does anyone know a way in which to achieve this either through the [Attribute] line itself of some function of Autofac during registation?
The ActionFilterAttribute:
public class GRMSActionLoggingFilter : ActionFilterAttribute {
private readonly IGRMSCoreServices _grmsCoreServices;
private readonly ILoggingService _loggingService;
public GRMSActionLoggingFilter(IGRMSCoreServices grmsCoreServices, ILoggingService loggingService) {
_grmsCoreServices = grmsCoreServices;
_loggingService = loggingService;
}
public GRMSActionLoggingFilter() { }
public override void OnActionExecuting(ActionExecutingContext actionContext) {...}
public override void OnActionExecuted(ActionExecutedContext actionContext) {...}
}
Assigning the attribute to the base controller:
// This currently compiles but will fail during run time as the IGRMSCoreSerivces and ILoggingService will both be null. Need to property inject these services somehow.
[GRMSActionLoggingFilter]
Anyone have any idea to achieve this?
You cannot (easily) inject runtime values to attributes.
This is how attributes work in C# - you can only pass constant values of certain types. You can read more about it here.
In order to achieve desired functionality in Orchard you need to split your code into two components:
a marker attribute class you put on your action
an action filter class inheriting from FilterProvider and implementing IActionFilter
The way it works is that you put an attribute on some action and then use the action filter to check existence of that attribute (using filterContext.ActionDescriptor.GetCustomAttributes(...)). If an attribute exists, do your stuff.
There are lots of examples of this technique in Orchard core. Check eg. the ThemedAttribute and ThemeFilter action filter classes.
The question is, as in title, whether the MVC model binder allow private constructors for the view model objects. Apparently it doesn't, saying MissingMethodException: No parameterless constructor defined for this object. even if there is a private parameterless constructor.
In case if there is no private constructor allowed, is there an arhitectural workaround?
Such constructor might be useful to ensure that only the model binder could create ViewModel objects whose fields might not be consistently filled - there would be no chance that in other parts of code some fields are forgotten to complete.
Entity Framework, in a similar situation, can use private constructor and private properties.
No, it does not.
If you want to prevent actual code from calling that constructor, you can add [Obsolete("For model binding only", true)] to a public constructor. This will cause a compiler error if the constructor is explicitly called.
You can always write a custom model binder that does support private/protected ctors.
I have a generic IRepository that has 2 constructors, one have none parameters, other has the datacontext as parameter.
I want to define to structuremap to aways in this case use the parameterless constructor.
I want a way to create a parameterless contructor, other solutions that I have seen, they create a new Datacontext and pass it to the constructor that has parameters.
By default, StructureMap will use the constructor with the most arguments. In your case, since you want it to use the parameterless constructor, use the DefaultConstructorAttribute:
[DefaultConstructor]
public void Repository<T>() { }
public void Repository<T>(DataContext dataContext) { }