Is there any way to create an instance of ConstructorArgument using lambda expression instead of hardcoded string to define the name of the property?
Something like this:
var validator = Ioc.Kernel.Get<Validators.Security.UserGroupValidator>(new ConstructorArgument( x => x.ValidationDictionary, new ValidationDictionary())
In my case, the ValidationDictionary is not the same in many places and for this reason, I can't use a Provider.
You can use the ToConstructor binding like
http://www.planetgeek.ch/2011/05/28/ninject-constructor-selection-preview/
Bind<UsergroupValidator>().ToConstructor(_ => new Usergroupvalidator(new ValidationDictionary());
Or even let the validation dictionary be injected as defined in the blogpost.
Related
I tried to define a generic loading method.
I call this generic loading method with an array of expressions like this:
var includes = new Expression<Func<CatalogItem, object>>[]
{
ci => ci.Catalog.Select(ci => ci.Supplier.Region),
ci => ci.Test
}
In the method I create an IQueryable:
IQueryable<TAggregateRoot> queryable = dbContext.Set<TAggregateRoot>();
Then for each Expression I want to load the respective data like this:
foreach (var include in includes)
{
queryable = queryable.Include(include);
}
But this only works when the Expression is only one level. With multiple levels it throws an error.
Since there is no ThenInclude I have to use the EntityFrameworkQueryableExtensions. I tried it like this
queryable = EntityFrameworkQueryableExtensions.ThenInclude(queryable, include);
But this does not work either.
I cannot find any documentation to this problem. How do I solve this problem and how do I use EntityFrameworkQueryableExtensions.ThenInclude?
Instead of passing an expression to the Include() method, there are two overloads you can use that take strings.
The first takes either a single property or multi-level properties like so:
Include("property1")
OR
Include("property1.property2.property3")
The second takes advantage of the nameof() method like so:
Include(nameof(property1), nameof(property2), nameof(property3))
And if you have a generic loading method that takes an array of strings to iterate over and "Include" (in precisely the same fashion you are iterating over your array right now), then you can use the first overload (one string) and do something like this:
MyGenericRepo.MySetInclude(new string[] {$"{nameof(ParentEntity.ChildEntity)}.{nameof(ChildEntity.GrandchildEntity)}"});
So you are still only using the one Include() method without adding any additional logic to your repository, but you can now "include" as many levels as you wish.
To see the origins of these overloads, you can check it out here
I am able to get a list of all the registered types by doing
var myTypes = kernel.Get<List<IMyInterface>>();
The MyType implementations need to take in a constructor argument though. I thought I could accomplish this by doing
kernel.Get<List<IMyInterface>>(
new ConstructorArgument("argName", argValue ) );
but this doesn't seem to work. I get an exception saying it's trying to resolve the parameter "argName" and can't. I'm guessing it's trying to use that arg for the List, and not each type in the list.
Is there a way to do this?
Update:
I'm able to do this in a round about way by doing
var types =
from t in typeof(IMyInterface).Assembly.DefinedTypes
where typeof(IMyInterface).IsAssignableFrom(t)
where t.IsClass
select (IMyInterface)kernel.Get(t,
new ConstructorArgument("argName", argValue));
This is not ideal.
Update:
I ended up changing my class constructor to not take in the parameter. I think it was not a good DI practice the way I had it working.
You can specify constructor arguments in the type Bindings
kernel.Bind<IMyInterface>().To<MyType>().WithConstructorArgument("argName",argValue);
With that binding in place, argValue will be injected into MyType constructor.
UPDATE:
If the argument is known only in runtime, you could do it like this:
In the binding get the value for construtor from request parameters:
kernel.Bind<IMyInterface>().To<MyType>().WithConstructorArgument("argName",
r => r.Parameters.First().GetValue(r.Request.ParentContext, r.Request.Target));
When creating instance, pass the parameter into request:
kernel.Get<List<IMyInterface>>( new Ninject.Parameters.Parameter("argName",argValue) );
If you want all registered types you should use GetAll<T> instead of Get<List<T>>:
kernel.GetAll<IMyInterface>(new ConstructorArgument("argName",argValue));
you can materialize that as a list if you really need to using LINQ's ToList.
Is it possible to use AutoMapper with a single property?
I would like to convert a string value of comma delimited values to a list of values separated by a line feed on the UI.
The current custom converters only seem to work at the class level, and because the dest and source types are both string I can't create a single map based on .
How would I apply the custom converter on a single property? Or should the custom resolver be used instead?
You may use a custom resolver or map the property by calling your convert logic in a MapFrom lambda:
Mapper.CreateMap<TSource, TDest>().ForMember(dto => dto.DestPrp,
e => e.MapFrom(o => ConvertTo(o.SourceProp)))
I'm trying to create a method signature that takes multiple properties of various type using
I would call it something like this:
AllPropertiesExcept(() => Property1, () => Property2)
This method almost work, except that the type of the properties have to be the same. I'm only going to use the property name, but want to use lambda expression to enable easy refactoring.
public static string MyMethod<T>(params Expression<Func<T>>[] propertyExpression)
I would use AllPropertiesExcept(params Expression<Func<object>>[] properties), you can still get the property names out of it, but it doesn't matter what type the property is.
Edit: However, I would tend to use it the other way round - instead of excluding properties I don't want to see, I would include properties I want to see. The reason is simple - to make your way work, you still need reflection - with my way, you could easily use the Func you get to get the actual data directly.
Edit 2 (getting the property name out of an expression):
Expression<Func<object>> obj = something; // you get this in your method
((obj.Body as UnaryExpression).Operand as MemberExpression).Member.Name
I can really advise you to use LinqPad for such things, you can easily drill down objects via Dump(), which displays the objects very user friendly. Just recreate a small example and experiment.
Does the method AllPropertiesExcept() return anything? Otherwise you could make a fluent interface (using method chaining):
AllPropertiesExcept(() => Property1)
.And(() => Property2)
.And(() => Property3);
Even if the AllPropertiesExcept() method returns something, you can defer the execution until you invoke a method at the end of the method chain:
var foo = AllPropertiesExcept(() => Property1)
.And(() => Property2)
.And(() => Property3)
.DoSomeThing();
I think what you need is to understand the ModelMetadata class documented here:
http://msdn.microsoft.com/en-us/library/system.web.mvc.modelmetadata.aspx
This class is used in ASP.NET MVC in situations like Html.LabelFor(x -> x.Name)
An expression is passed to the ModelMetadata.FromLambdaExpression Method documented here:
http://msdn.microsoft.com/en-us/library/ee428393.aspx
After understanding how it is used in MVC, you could create your own code with some informed knowledge of how it was applied elsewhere.
Is it possible to project every property of an object and add more, without specifically listing them all. For instance, instead of doing this:
var projection = from e in context.entities
select new QuestionnaireVersionExtended
{
Id = e.Id,
Version = e.Version,
CreationDate = e.CreationDate,
...
many more properties
...
NumberOfItems = (e.Children.Count())
};
Can we do something like this:
var projection = from e in context.entities
select new QuestionnaireVersionExtended
{
e,
NumberOfItems = (e.Children.Count())
};
Where it will take every property from e with the same name, and add the "NumberOfItems" property onto that?
No this is not possible. The select clause of a LINQ expression allows for normal C# expressions which produce a value. There is no C# construct which will create an object via an object initializer in a template style manner like this. You'll need to either list the properties or use an explicit constructor.
If you add a constructor to QuestionnaireVersionExtended that takes your entity plus NumberOfItems, you can use the constructor directly:
var projection = from e in context.entities
select new QuestionnaireVersionExtended(e, NumberOfItems = (e.Children.Count()));
There is, however, no way to tell the compiler "just copy all of the properties across explicitly."
There are several ways that you could accomplish this but they all are going to be nightmares.
1.) Overload a constructor and copy all of the values there (however that is what you are trying to get away from.
2.) Use reflection to copy the properties over (many bad side effect, not recommended)
3.) USE THE DECORATOR PATTERN. It looks like you added values to the original class so I think this would be the perfect time to use a decorator. This would also make it so that as properties are added they aren't missed. It would break the compile, however this solution isn't perfect if the object being decorated is sealed.