Generic extension method refactor - c#

I'm wondering if the following can be refactored in the way I would like it:
[EditorBrowsable(EditorBrowsableState.Never)]
public static class ListExtensions
{
public static PaginatedList<Y> ToMappedPaginatedList<T, Y>(this PaginatedList<T> source)
{
var mappedList = new List<Y>();
Mapper.Map(source, mappedList);
return new PaginatedList<Y>(mappedList, source.PageIndex, source.PageSize, source.TotalCount);
}
}
The Mapper.Map line is using AutoMapper to map properties from an entity to a DTO object.
This is called like this:
var list = await _service.GetAllAsync(pageIndex, _pageSize);
var dtoList = list.ToMappedPaginatedList<Farmer, FarmerDTO>();
but I'd like to call it like this:
var dtoList = list.ToMappedPaginatedList<FarmerDTO>();
This saves a little bit of typing and you don't always need to be aware of the source list its type. Unfortunately this code doesn't work and I'm not sure if there's a simple answer.
Anyone got an idea?
Thanks in advance.
Yannick

If you have access to the PaginatedList class, putting the method in there will enable the syntax you desire since the instance knows what it's own type is.
I don't recommend the following but it demonstrates a way to take advantage of type inference.
You can enable type inference by adding a 2nd "useless" parameter of type Y.
If you pass default(FarmerDTO) as the 2nd parameter, a null will be passed as the parameter value but the intended type will be inferred.
[EditorBrowsable(EditorBrowsableState.Never)]
public static class ListExtensions
{
public static PaginatedList<Y> ToMappedPaginatedList<T, Y>(this PaginatedList<T> source, Y destinationPlaceholder)
{
var mappedList = new List<Y>();
Mapper.Map(source, mappedList);
return new PaginatedList<Y>(mappedList, source.PageIndex, source.PageSize, source.TotalCount);
}
}
Call it like this:
var result1 = s.ToMappedPaginatedList(default(FarmerDTO));
Fair warning. I've never used this because I find the resulting code to be non-obvious as to what it is doing.

Either you call a method and specify all the generic arguments or you specify none and let the compiler infer them, there's no support for partial inference.
As such, the only way to get your code to compile is to make ToMappedPaginatedList take 1 generic parameter, instead of two.

Related

How to call a generic method using a type returned from a different method?

I have two types Person and Organisation both inheriting from IContact.
I have a method that returns one of these types based on some logic
private Type GetPersonOrOrganisation(string some variable)
{
either returns Person or Organisation type
}
I have a method which queries the database for Persons or Orgs:
public static IQueryable<T> Query<T>(this IUow uow) where T : IContact
{
return uow.Query<T>();
}
My question is how can I use the Type returned from GetPersonOrOrganisation to call query.
So say:
var contactType = GetPersonOrOrganisation(string some variable);
var contact = Query<contactType>();
where contactType will be either Person or Organisation.
Well obviously that won't compile and that's my question. How to make the query on the right type from the database based on what is returned from GetPersonOrOrganisation.
Moving between Type and generics is a major pain; the only answer without refactoring is: reflection; something like:
var method = typeof(SomeType).GetMethod("Query").MakeGenericMethod(contactType);
// this is to getch your Query<T>(this IUow) method
var contact = (IContact)method.Invoke(null, new object[] { uow });
which is pretty horrible. If possible, I would suggest rewriting your Query<T> method as a Query(Type type) method (returning IContact), which still trivially allows a generic Query<T> helper method for the existing code, via return (T) Query(typeof(T));. The reverse is not the case, however.
If you were passing an instance of type T into the method, there are some tricks you can do to simplfiy this, by using dynamic to perform the type/generics/method resolution for you.
You cannot do that.
However, what you are trying to accomplish actually?
Consider using ArrayList or List instead. As modification about which type to be returned in Query, you can tweak the method like this:
public static IQueryable<T> Query<T>(this IUow uow, Type returnType) where T : IContact
{
if(returnType is IContact) // code here
}
That is quick code which maybe has error.
This stackoverflow link already has discussion about this:
using type returned by Type.GetType() in c#

C#: Why doesn't generic type inference work when there are multiple type arguments?

Here are two samples:
This works fine:
void Main()
{
var list = Queryable.ProjectTo(typeof(Projection));
}
public static class QueryableExtensions
{
public static ProjectionList<T> ProjectTo<T>(this IQueryable<T> queryable, Type projectionType)
{
return new ProjectionList<T>(queryable, projectionType);
}
}
This throws the following error:
Using the generic method
'QueryableExtensions.ProjectTo(System.Linq.IQueryable)'
requires 2 type arguments
void Main()
{
var list = Queryable.ProjectTo<Projection>();
}
public static class QueryableExtensions
{
public static ProjectionList<T, P> ProjectTo<T, P>(this IQueryable<T> queryable)
{
return new ProjectionList<T, P>(queryable);
}
}
Of course the first example requires 1 type argument, however the compiler can figure out what it is so I don't need to supply any. The second example requires 2 type arguments but the compiler knows what T is so why does it not only require the one that cannot be inferred?
For the record I am using the first example just fine in my code, but I like the syntax of the second much better and there may be a case where I would like to have the generic type of the projection. Is there any way to achieve this or am I barking up the wrong tree?
Thanks!
The issue is not the 2 parameters, but rather: from where would it infer it? Generic parameter inference only looks at parameters, and specifically does not consider return types. There is nothing in the parameters that would suggest P. It is required that either generic type inference provides all of them, or all of them are specified explicitly. Interestingly, there was once mention of "mumble-typing" which, as I interpret it (since it never got defined fully) would have allowed you to mix and match, like you want. Imagine:
blah.ProjectTo<?,SomeType>();
(the exact syntax doesn't matter since this language feature doesn't exist) - but it would mean "there are 2 genericmtype arguments; you (the compiler) figure out the first parameter; the second is SomeType".
That's because generic parameter inference works only with input parameters. In your second example the P parameter appears only at the return type, thus the inference cannot work. So when you write:
var list = Queryable.ProjectTo<Projection>();
T is Projection but what's P for you?
But even if you write:
ProjectionList<Projection, FooBar> list = Queryable.ProjectTo();
it still wouldn't work.

C# simpler run time generics

Is there a way to invoke a generic function with a type known only at run time?
I'm trying to do something like:
static void bar()
{
object b = 6;
string c = foo<typeof(b)>();
}
static string foo<T>()
{
return typeof (T).Name;
}
Basically I want to decide on the type parameter only at run time, but the function I'm calling depends on the type parameter.
Also I know this can be done with reflections... but it's not the nicest solution to the problem...
I'm sort of looking for dynamic features in C#...
I'm writhing a bridge between two classes the first one is basically a big tree with different types of of objects (composite by interface) the other is a sort of a "super visitor".
the supper visitor accepts key-value dictioneries that map types to object it looks like:
dic.Add(object value)
and T is not necessarily the type of the value... a lot of times it isn't...
I know it's written poorly, but i can't fix it...
I can work around it, but only at runtime...
I already did it with reflections, but if there's a better way to do it without them i would be happy to learn...
Thank you
This is a bit of a hack but you can get dynamic to do the reflection work for you by something like,
class Program
{
static void Main(string[] args)
{
var b = 6;
var t = (dynamic)new T();
var n = t.Foo(b);
}
class T
{
public string Foo<T>(T a)
{
return typeof(T).Name;
}
}
}
Here the dynamic call will extract the type of b and use it as a type parameter for Foo().
You can use dynamic keyword if you're using .NET 4. In a word, the type of the variable will be resolved at run time so it is a super generic type ;) You can read a article here or read the MSDN documentation
Saly refelction is THE solution to the problem, whether it is nice or not is irrelevant here. It is the runtime designed mechanism to achieve exactly this. As there is no parameter or generics to use as input, this is the only way to do it - it is also senseless. As in: your example is bad. Because in the example the type is hardcoded.
If the method where b exists has b as generic parameter, the type is available for passing to foo. If not - reflection is THE way to go, albeit the syntax looks clumsy. Only one time, though.
This I believe is the only way:
var foo = typeof(Foo<>).MakeGenericType(typeof (bar));
You can set up a class which takes a type parameter at run time which can be used in the methods in that class.
public class GenericClass<T>()
{
ICommonInterface TheObject;
public GenericClass(T theObject)
{
TheObject = theObject;
}
public string GetName()
{
return TheObject.Name;
}
}
But this is only really useful if the Types being passed in share interfaces so have common properties between them. In your example it seems that relection is the answer as depending on the type you want to access specific properties.

Dictionary of Action<T> Delegates

I have object XML serialized messages coming into a class called MessageRouter. The XML contains the Type name it it was serialized from, and I need to be able to invoke different delegate methods depending on the type that are not known until runtime. I'm not extremely strong in generics so hopefully this will make sense to someone...
I'd like MessageRouter to provide a RegisterDelegateForType method like so:
myMessageRouter.RegisterDelegateForType(new Action<MySerializableType>(myActionHandler));
And then store the types, or the type's string representation in a Dictionary like this:
Dictionary<Type, Action<T>> registeredDelegates;
That way, I can do something like the following pseudocode, calling the type's assigned delegate and passing the deserialized object:
Type xmlSerializedType = TypeFromXmlString(incomingXml);
object deserializedObject = DeserializeObjectFromXml(xmlSerializedType, incomingXml);
// then invoke the action and pass in the deserialized object
registeredDelegates[xmlSerializedType](deserializedObject);
So my questions are:
How do you define a Dictionary that can contain a Type as a key and a generic Action<T> as a value, and have the RegisterDelegateForType method populate the dictionary?
If that's not possible, what's the best way to do this?
You cannot do this as described, for quite obvious reasons - even if somehow allowed, the last line of code in your example (the one which retrieves a delegate and then calls it) would be non-typesafe, as you're calling an Action<T> - which expects T as an argument - and yet passing it deserializedObject, which is of type object. It wouldn't work in plain code without a cast, why would you expect to be able to circumvent the type check for your case?
In the simplest case, you can do something like this:
Dictionary<Type, Delegate> registeredDelegates;
...
registeredDelegates[xmlSerializedType].DynamicInvoke(deserializedObject);
Of course this will allow someone to add a delegate which takes more or less than one argument to the dictionary, and you'll only find out at DynamicInvoke call, at run-time. But there isn't really any way to define a type which says "any delegate, but with 1 argument only". A better option might be this:
Dictionary<Type, Action<object>> registeredDelegates
and then registering types like this:
myMessageRouter.RegisterDelegateForType<MySerializableType>(
o => myActionHandler((MySerializableType)o)
);
The above snippet uses C# 3.0 lambdas, but you can do the same - if slightly more verbose - with C# 2.0 anonymous delegates. Now you don't need to use DynamicInvoke - the lambda itself will do the proper cast.
Finally, you can encapsulate the lambda creation into RegisterDelegateForType itself by making it generic. For example:
private Dictionary<Type, Action<object>> registeredDelegates;
void RegisterDelegateForType<T>(Action<T> d)
{
registeredDelegates.Add(typeof(T), o => d((T)o));
}
And now the callers can just do:
RegisterDelegateForType<MySerializableType>(myHandler)
So it's completely typesafe for your clients. Of course, you're still responsible for doing it right (i.e. passing an object of the correct type to the delegate you retrieve from the dictionary).
I am not sure that this completely answers your question, but here is a class I wrote that will accomplish what you want. I couldn't tell if you want your Action delegate to take a typed object or not, but in your pseudo code, you pass it an "object" to deserialize so I wrote my class accordingly and it therefore does not use generics:
public delegate void Action(object o);
public class DelegateDictionary {
private IDictionary _dictionary = new Hashtable();
public void Register<T>(Action action) {
_dictionary[typeof(T)] = action;
}
public Action Get<T>() {
return (Action)_dictionary[typeof(T)];
}
public static void MyFunc(object o) {
Console.WriteLine(o.ToString());
}
public static void Run() {
var dictionary = new DelegateDictionary();
dictionary.Register<string>(MyFunc);
// Can be converted to an indexer so that you can use []'s
var stringDelegate = dictionary.Get<string>();
stringDelegate("Hello World");
}
}
I believe this will accomplish what you want.

Create Generic Class instance based on Anonymous Type

I have a class ReportingComponent<T>, which has the constructor:
public ReportingComponent(IQueryable<T> query) {}
I have Linq Query against the Northwind Database,
var query = context.Order_Details.Select(a => new
{
a.OrderID,
a.Product.ProductName,
a.Order.OrderDate
});
Query is of type IQueryable<a'>, where a' is an anonymous type.
I want to pass query to ReportingComponent to create a new instance.
What is the best way to do this?
Kind regards.
Write a generic method and use type inference. I often find this works well if you create a static nongeneric class with the same name as the generic one:
public static class ReportingComponent
{
public static ReportingComponent<T> CreateInstance<T> (IQueryable<T> query)
{
return new ReportingComponent<T>(query);
}
}
Then in your other code you can call:
var report = ReportingComponent.CreateInstance(query);
EDIT: The reason we need a non-generic type is that type inference only occurs for generic methods - i.e. a method which introduces a new type parameter. We can't put that in the generic type, as we'd still have to be able to specify the generic type in order to call the method, which defeats the whole point :)
I have a blog post which goes into more details.

Categories