I am currently trying to set a field which I need in business logic which in this case is Lazy.
(yes not the property, it is necessary to set the field)
I get the error that Lazy can not be converted to Lazy
as you can see:
Object of type
'BusinessLogic.Lazy1[System.Object]'
cannot be converted to type
'BusinessLogic.Lazy1[BusinessLogic.ArtikelBLL]
I use this line to get a dynamic repository.
dynamic repository = Activator.CreateInstance(typeof(GenericRepository<>).MakeGenericType(typeArgs));
Then I try to set the value of the field but it fails:
fInfo.SetValue(obj, Lazy.From(() => repository.GetDataById(id)));
I have tried to solve it many different ways.
Somehow I have to cast repository.GetDataById(id) to the Entity it is looking for, which in this case is ArtikelBLL (which i can get through pInfo.PropertyType).
But by doing (ArtikelBLL)repository.GetDataById(id) it will not remain object orientated.
Can anybody please help me with this?
The simplest way would be to just use a cast inside the lambda:
fInfo.SetValue(obj, new Lazy<GenericBLL>(
() => (ArtikelBLL) repository.GetDataById(id)));
After all, that's the type the Lazy<T> wants.
EDIT: If you're trying to do this dynamically, I suggest you write a generic method like this:
public Lazy<T> CreateLazyDataFetcher<T>(dynamic repository)
{
return new Lazy<T>(() => (T) repository.GetDataById(id));
}
Then call that method with reflection. (Using MethodInfo.MakeGenericMethod(...).Invoke(...))
Related
I have a generic method
var propertyResolverMethod = _propertyResolver
.GetType()
.GetMethod(
nameof(_propertyResolver.GetEntities),
new[] { typeof(string), typeof(string) })
?.MakeGenericMethod(_itemType);
and the invocation
var recommendedItems = propertyResolverMethod
?.Invoke(
_propertyResolver,
new object[] { itemId, ResolvedCollectionId });
It on the compile-time it returns an object, but on runtime, it returns IQueryable<Item> this item is the item from _itemType and we find out its type only on runtime, but I know that it has a collection inside Item.RelatedItems that I need to get. Tried already casting to dynamic, but does not work for my case, I know that's somehow solvable via Expressions.
Should be iteratable like this
var itemIds = recommendedItems?.Select(i => i.RelatedItems.Select(s => s.ItemID));
But it's not possible without a proper cast
Hmm..
So if I get you correctly, you know this method returns an IQueryable<Item> where Item is the type previously stored in _itemType and you also know for a fact that this type always defines RelatedItems which in turn are an IEnumerable<T> or IQueryable<T> with Tdefining ItemID?
Is there a type that all possible _itemTypes inherit from that has RelatedItems defined? If so, you could try casting to that...
Else you could do more Reflection magic:
If you know that your result is an IQueryable<TItem>, you can extract the property-getter for RelatedItems with Reflection and pass that to the Select-function (which you can get by eithre casting to IQueryable<object> or by using ... again ... Reflection.
But to be honest that would be a very, very dirty way to do it and I would only do it as a last resort.
My first instinct right now would be to try refactoring the containing class (_itemType hints to me that this is a member field), so it is generic as well (inheriting from a non-generic class if you need that), so the class knows the type through its own type parameter.
Another solution would be to have a function like this:
private <Type of itemIDs> GetRelatedItemIds<TItem>(object source) {
return ((IQueriable<TItem>)source)?.Select(i => i.RelatedItems.Select(s => s.ItemID));
}
Now get that method via Reflection and use MakeGenericMethod(_itemType) on it, then invoke it with your result.
Just beware that your current selection will return a nested enumerable/queryable which each entry being a list of ItemIDs. If you didn't mean to do that, use SelectMany instead of the first Select which will automatically concatenate the inner enumerables/queryables.
I hope this helps you find a solution.
In my booking object I keep an object reference list with the Type and WorkflowStepTypeId of the corresponding document. I then want to use the type in a Where to find the suitable document, and retrieve it by id. However, when compiling the transformer to RavenDB it says it doesn't know what my type is.
Code:
public class BookingToTrainingTransformer
: RavenTransformerBase<Booking, BookingToTrainingTransformer.Result>
{
public class Result
{
}
public BookingToTrainingTransformer()
{
TransformResults = results =>
from result in results
let trainingWorkflow = LoadDocument<TrainingWorkflow>(result.WorkflowSteps
.FirstOrDefault(a => a.WorkflowStepType == typeof(Trainingworkflow))
.WorkflowStepTypeId)
}
}
To clarify, I know that RavenDB wouldn't know what my type is. On the database side, I simply want it to make a string of both types and compare those strings. However, for refactoring purposes it would be great to know that the type is actually used in said transformer so if it ever gets refactored, the transformer also automatically gets refactored.
Is what I want possible?
You want it to compare actual types so that if you refactor the type later, the transformer will still work?
No, that's not possible.
If I'm understanding your question right, can WorkflowStepType be a type name? If you refactor the type name later, sure, you'd still need to update the WorkflowStepType property in the database. But in your transformer, it'd just look like this:
.FirstOrDefault(a => a.WorkflowStepType == nameof(Trainingworkflow))
I am trying to get the actual object that is contained within a list that itself is contained within a task.
e.g. method has the following signature e.g.
public async Task<List<Dictionary<string,object>>> GetData()
i am currently using something like this:
var member = type.GetMembers()[0];
var returntype = member.ReturnType.GetGenericArguments();
var temp = member.ReturnType.GetGenericArguments()[0];
if (temp.GetGenericArguments().Count() > 0)
{
temp.GetTypeInfo().GetGenericArguments();
var innerttype = temp.GetGenericArguments()[0].FullName;
}
Currently the above code (which is not complete but just an extract from actual code) return system.object as fullname instead of Dictionary.
Any suggestions to solve this are welcome.
If you declare your dictionary to be of type <string, object> and and only ever insert objects inside it and not something higher up in the graph, you'll only ever get object typed objects out of it.
If you're storing all kinds of things in there and need to get their concrete type so you can interact with them, try to make them all conform to an interface first. Then, put the interface type in there replacing "object." If that doesn't work you can use generics. However, you'll still need to know the type ahead of time in order to be able to interact with it.
If you really have no idea what's in there and want to dig into it dynamically, that's precisely what Reflection was built for. You could also look into the dynamic type.
I need to find out if a Type I'm working with is a Generic 'container', for example if I have a List<int> I need to check if I'm working with a List (I know how to get whether I'm working with an int), how would I do that? (I'm thinking Reflection). Another example, I have a class called StructContainer<T>, I need to find the word (name) 'StructContainer', I'm not too bothered with what 'T' is, using reflection I get StructContainer'1, would hate to have to do some string splitting etc /EDIT: Just to explain further, StructContainer<int> I need 'StructContainer', Tuple<int> I need 'Tuple', List<int> I need 'List' and so forth
Your first question can be achieved in multiple ways:
Check whether your object implements IEnumerable<T>: yourObject is IEnumerable<int>. This only works if you know the type of the object in the container (int in this case)
Use the same solution I described below, just change StructContainer to List.
As to your second question, you can do this:
var yourObject = new StructContainer<int>();
var yourType = yourObject.GetType();
if(yourType.IsGenericType &&
yourType.GetGenericTypeDefinition() == typeof(StructContainer<>))
// ...
string type = yourObject.GetType().Name.Split('`')[0];
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.