Unable to cast resolved object to generic abstraction autofac C# - c#

Hey I try to cast my object to interface which this object should implements. But during executing code I have following error:
Unable to cast object of type GetTreeHandler to IQueryHandler, IQuery<Tree>.
Why? Everything seems to be ok.
Any idea without using dynamic?
QueryDispatcher
public async Task<TResult> ExecuteAsync<TResult>(IQuery<TResult> query)
{
if (query == null)
{
throw new ArgumentNullException("Query can not be null.");
}
var handlerType = typeof (IQueryHandler<,>).MakeGenericType(query.GetType(), typeof (TResult));
var handler = _context.Resolve(handlerType);
IQueryHandler<IQuery<TResult>, TResult> castedHandler = (IQueryHandler<IQuery<TResult>, TResult>) handler;
return (TResult) await castedHandler.ExecuteAsync(query);
}
GetTreeHandler
public class GetTreeHandler : IQueryHandler<GetTree, Tree>
{
private readonly ProductContext _context;
public string Name { get; set; }
public GetTreeHandler(ProductContext context)
{
_context = context;
}
public async Task<Tree> ExecuteAsync(GetTree query)
=> await Task.FromResult(
_context.Trees.FirstOrDefault(x => x.Id == query.Id)
);
}
EDIT
My current solution(partially works):
public async Task<TResult> ExecuteAsync<TResult>(IQuery query) where TResult : class
{
if (query == null)
{
throw new ArgumentNullException("Query can not be null.");
}
var handlerType = typeof (IQueryHandler<,>).MakeGenericType(query.GetType(), typeof (TResult));
var handler = _context.Resolve(handlerType);
return await (Task<TResult>)
handler.GetType()
.GetMethod("ExecuteAsync")
.Invoke(handler, new object[]{query});
}
Why partially?
Eg. handlers:
Doesn't work:
public class GetIndexesHandler : IQueryHandler<GetIndexes, IEnumerable<AssocIndexDto>>
Works:
public class GetIndexesHandler : IQueryHandler<GetIndexes,AssocIndexDto>
As you can see these two classes implements the same interface but with different second parameter type.
The problem is that Resolve method cannot find the registered service, but if I try to debug this code, I can see that the wanted service is registed correctly, but it can't be found.
Have you any idea how to solve it?

You are trying to cast an IQueryHandler<GetTree, Tree> to an IQueryHandler<IQuery<Tree>, Tree>, but that would only work when IQueryHandler<TQuery, TResult> was specified as:
interface IQueryHandler<out TQuery, TResult>
Notice the out argument here.
The out keyword marks TQuery as an output argument. In case a generic type argument is marked as output argument, it allows us to cast the interface to something more generic. An IEnumerable<string> for instance can be casted to IEnumerable<object> since IEnumerable<string> will return strings, and they can be represented as objects.
For in arguments however, the opposite holds. When looking at an Action<in T> for intance, we are allowed to cast an Action<BaseType> to Action<SubType>, since the action would always be able to process SubTypes as well. On the other hand, it would be impossible to cast Action<BaseType> to Action<object> since that would allow us to pass in a string to the action as well (since string is an object), but that would then obviously fail at runtime.
So casting an IQueryHandler<GetTree, Tree> to IQueryHandler<IQuery<Tree>, Tree> would only be possible if TQuery is marked with an out keyword, but clearly TQuery is an input argument. The CLR therefore forbids the conversion, since it could lead to errors at runtime.
In your case however, this problem would not exist, because you know that the passed in type always fits. But remember, the CLR is unable to check this, and is therefore blocking the conversion.
One solution is, as I described on my blog, to use the dynamic keyword as follows:
public async Task<TResult> ExecuteAsync<TResult>(IQuery<TResult> query)
{
var handlerType =
typeof(IQueryHandler<,>).MakeGenericType(query.GetType(), typeof(TResult));
dynamic handler = _context.Resolve(handlerType);
return (TResult)await castedHandler.ExecuteAsync((dynamic)query);
}
Another option is to specify and register a generic wrapper type that implements an interface that lacks the TQuery generic type. This way you can prevent using dynamic altogether:
public interface IWrapper<TResult>
{
Task<TResult> ExecuteAsync(IQuery<TResult> query);
}
public async Task<TResult> ExecuteAsync<TResult>(IQuery<TResult> query)
{
var wrapperType =
typeof(Wrapper<,>).MakeGenericType(query.GetType(), typeof(TResult));
var wrapper = (IWrapper<TResult>)_context.Resolve(wrapperType);
return wrapper.ExecuteAsync(query);
}
// Don't forget to register this type by itself in Autofac.
public class Wrapper<TQuery, TResult> : IWrapper<TResult>
{
private readonly IQueryHandler<TQuery, TResult> handler;
public Wrapper(IQueryHandler<TQuery, TResult> handler) { this.handler = handler; }
Task<TResult> IWrapper<TResult>.ExecuteAsync(IQuery<TResult> query) =>
this.handler.ExecuteAsync((TQuery)query);
}

Related

C# using statement with return value or inline declared out result variable

I am wondering if there is some way to optimize the using statement to declare and assign its output together (when it is a single value).
For instance, something similar to the new way to inline declare the result variable of an out parameter.
//What I am currently doing:
string myResult;
using(var disposableInstance = new myDisposableType()){
myResult = disposableInstance.GetResult();
}
//That would be ideal
var myResult = using(var disposableInstance = new myDisposableType()){
return disposableInstance.GetResult();
}
//That would be great too
using(var disposableInstance = new myDisposableType(), out var myResult){
myResult = disposableInstance.GetResult();
}
Thanks for your input.
You can use extension method to "simplify" this usage pattern:
public static class Extensions {
public static TResult GetThenDispose<TDisposable, TResult>(
this TDisposable d,
Func<TDisposable, TResult> func)
where TDisposable : IDisposable {
using (d) {
return func(d);
}
}
}
Then you use it like this:
string myResult = new myDisposableType().GetThenDispose(c => c.GetResult());
This is funny, because I started reading Functional Programming in C# a couple of days ago, and one of the first examples is along the lines of:
public static TResult Using<TDisposable, TResult>(TDisposable disposable, Func<TDisposable, TResult> func)
where TDisposable : IDisposable
{
using (disposable)
{
return func(disposable);
}
}
Usage:
var result = Using(new DbConnection(), x => x.GetResult());
Notice that, unlike the other answers posted, this function has absolutely no responsibility but get the result of func, regardless of TDisposable.
No, there is no such shortcut. Your original way is right.
You could wrap this in a function if you do it often enough
public class Utilities
{
public static TReturn GetValueFromUsing<T,TReturn>(Func<T,TReturn> func) where T : IDisposable, new()
{
TReturn result = default(TReturn)
using(var instance = new T())
result = func(instance);
return result;
}
}
usage
var result = Utilities.GetValueFromUsing<myDisposableType,string>(x => x.GetResult());
But man would that be overkill.
The using instruction cannot be used as r-value, and therefore there is no way to assign a value from it.
However, there is a special case to this, and you can use it where convenient: You can return a result from inside the using block.
int F(int arg)
{
using (disposable = GetObj())
{
return disposable.Calculate(arg);
}
}
This form is often communicating the purpose better than a local variable assignment. You can even turn it into a template method, where the method would apply the using construct and then call a strategy and return its result.
class Useful<TDisposable> where TDisposable : IDisposable
{
private Func<TDisposable> Factory { get; }
public Useful(Func<TDisposable> factory)
{
this.Fatory = factory;
}
public TResult SafeDo<TResult>(Func<TDisposable, TResult> operation)
{
using (TDisposable obj = this.Factory())
{
return operation(obj);
}
}
}
This class is completely reusable and its single responsibility is to ensure that disposable components are disposed on use. Instead of working directly with a disposable class, you can wrap it into this wrapper class and consume it that way and you'll have a strict lifetime control over the disposable objects:
void Worker(Useful<MyDisposableClass> wrapper)
{
int arg = 5;
wrapper.SafeDo(disp => disp.Calculate(arg);
}
In this piece of code, the disp object would be constructed and disposed correctly. A concrete argument that would be required by the operation arg is taken from the closure.

Pass generic method omitting its parameters?

Is there a way to pass a method name in a generic manner, without passing its parameters, so it can be invoked by the method, with passed arguments?
Consider this example:
public class Client
{
public string Convert(int value)
{
return value.ToString();
}
}
public class Wrapper<TClient>
{
TClient Client;
public TResult Invoke<TArg, TResult>(Func<TClient, TArg, TResult> action, TArg arg)
{
return action(Client, arg);
}
}
I want to be able to pass to the wrapper the method of TClient I want to invoke, and pass the actual arguments along, all generically:
var wrapper = new Wrapper<Client>();
wrapper.Invoke(c => c.Convert, 5);
Is there any possible way to achieve that, without hard coding the method name, or losing its genericness (i.e. by using Delegate)?
Notes:
The Client is an external sealed class that exposes a gazillion methods each of many parameters. I want wrap its behavior and I don't mind writing all the necessary code in the wrapper, but the usage of the wrapper should be as clean as possible.
Update
I want to avoid the need to specify the parameters. The whole idea is having them inferred from the specified action.
You're very close to getting your code to run. There are two options.
First, you can try this:
public class Wrapper<TClient>
{
public TResult Invoke<TArg, TResult>(Func<TArg, TResult> action, TArg arg)
{
return action(arg);
}
}
Then call it like this:
var wrapper = new Wrapper<Client>();
wrapper.Invoke(wrapper.client.Convert, 5);
Or, alternatively, you can do this:
public class Wrapper<TClient>
{
public Wrapper(TClient client)
{
this.Client = client;
}
private TClient Client;
public TResult Invoke<TArg, TResult>(Func<TClient, TArg, TResult> action, TArg arg)
{
if (operation.Target != Client)
throw new ArgumentException(nameof(operation));
return action(this.Client, arg);
}
}
And call it like this:
var client = new Client();
var wrapper = new Wrapper<Client>(client);
wrapper.Invoke((c, a) => c.Convert(a), 5);
But, from your description of your problem, I don't see how either of these help and I don't see how to implement what you're asking. Perhaps you need to provide more detail as to what the underlying need you're trying to solve?
You want the expression being passed to Invoke to return a Func that accepts TArg. In code:
public class Wrapper<TClient>
{
TClient Client;
public TResult Invoke<TArg, TResult>(Func<TClient, Func<TArg, TResult>> action, TArg arg)
{
return action(Client)(arg);
}
}
You can then invoke it like so:
class Program
{
static void Main(string[] args)
{
var wrapper = new Wrapper<Client>();
string result = wrapper.Invoke<int, string>(c => c.Convert, 5);
}
}
Since you don't like the approach of having to explicitly specify type arguments, you can use a slightly different API (which comes with its own annoyances):
public class Wrapper<TClient>
{
TClient Client;
public void Invoke<TArg, TResult>(Func<TClient, Func<TArg, TResult>> action, TArg arg, out TResult result)
{
return action(Client)(arg);
}
}
You can call this like so, with the return type inferred from the out parameter:
class Program
{
static void Main(string[] args)
{
var wrapper = new Wrapper<Client>();
string result;
wrapper.Invoke(c => c.Convert, 5, out result);
}
}

Autofac: resolve an open generic with conditions on its type parameters

In an application using Autofac as its IoC container, I have a generic interface with two type parameters:
public interface IMapper<TSource, TTarget>
{
TTarget GetTarget(TSource source);
}
and a wrapper interface to dynamically select the appropriate IMapper<TSource, TTarget> depending on its input parameter types:
public interface IDynamicMapper
{
T GetTarget<T>(object source);
}
I want my implementation of IDynamicMapper to find at runtime the appropriate IMapper<TSource, TTarget> component, using Autofac, which has a TSource equal to source.GetType() and TTarget being a derived type of T (or T itself):
public class DynamicMapper : IDynamicMapper
{
private readonly ILifetimeScope _scope;
public DynamicMapper(ILifetimeScope scope)
{
this._scope = scope;
}
T IDynamicMapper.GetTarget<T>(object source)
{
Type sourceType = source.GetType();
Type targetBaseType = typeof(T);
//TODO: find an IMapper<TSource, TTarget> implementation where
// 1) Condition on TSource: typeof(TSource) == sourceType
// 2) Condition on TTarget: targetBaseType.IsAssignableFrom(typeof(TTarget))
// Many implementations can potentially match these criterias,
// choose the 1st one
// (this should not happen if the application is designed correctly)
if (mapper == null)
{
throw new ArgumentException(
"Could not find an IMapper<TSource, TTarget> implementation" +
" for the supplied parameters"
);
}
// call mapper.GetTarget(source) and return the result
// (mapper is probably dynamic, but its runtime type implements
// TTarget IMapper<TSource, TTarget>.GetTarget(TSource source))
}
}
All my components are registered to the Autofac container as their service interfaces in another part of the application (using assembly scanning for the record).
UPDATE 1
Based on Steven's pertinent answers I updated my interface as follow to use variance:
public interface IMapper<in TSource, out TTarget>
{
TTarget GetTarget(TSource source);
}
My dynamic mapper's GetTarget() method looks like this:
T IDynamicMapper.GetTarget<T>(object source)
{
Type sourceType = source.GetType();
Type targetBaseType = typeof(TTarget);
Type mapperType = typeof(IMapper<,>).MakeGenericType(sourceType, targetBaseType);
// This fails with ComponentNotRegisteredException
dynamic mapper = this._scope.Resolve(mapperType);
// This also fails (mapper is null):
// IEnumerable<object> mappers = (IEnumerable<object>)this._scope.Resolve(typeof(IEnumerable<>).MakeGenericType(mapperType));
// dynamic mapper = mappers.FirstOrDefault();
// Invoke method
return mapper.GetTarget((dynamic)source);
}
However, when calling Resolve(mapperType) or Resolve(typeof(IEnumerable<>).MakeGenericType(mapperType)), the component is not resolved, although it is present in the container's registrations, mapped to the service IMapper<TSource, TTarget>. The 1st call throws an exception and the 2nd one returns an empty enumerable.
This should do the trick:
T IDynamicMapper.GetTarget<T>(object source) {
Type mapperType = typeof(IMapper<,>).MakeGenericType(source.GetType(), typeof(T));
// Will throw when no registration exists.
// Note the use of 'dynamic'.
dynamic mapper = scope.Resolve(mapperType);
return (T)mapper.GetTarget<T>((dynamic)source);
}
Autofac does not support covariant generic types (ISomething<out T>). Another IoC container like Simple Injector could do the trick in this case, but to make it work with Autofac I ended up using another interface:
Services:
public interface IMapper<TSource, out TTarget> : IMapperLocator<TSource>
{
TTarget Extract(TSource source);
}
public interface IMapperLocator<TSource>
{
}
public interface IDynamicMapper
{
T Extract<T>(object source);
}
Implementation:
public class DynamicMapper : IDynamicMapper
{
private readonly ILifetimeScope _scope;
public DynamicMapper(ILifetimeScope scope)
{
this._scope = scope;
}
T IDynamicMapper.Extract<T>(object source)
{
// Get useful types
Type sourceType = source.GetType();
Type targetBaseType = typeof(TTarget);
Type mapperBaseType = typeof(IMapper<,>).MakeGenericType(sourceType, targetBaseType);
Type locatorType = typeof(IMapperLocator<>).MakeGenericType(sourceType);
Type enumType = typeof(IEnumerable<>).MakeGenericType(locatorType);
// Get all mapper implementations that take a TSource with the
// same type as the source object
var mappers = (IEnumerable<object>)this._scope.Resolve(enumType);
// Among all the mappers with the right TSource, select the one
// with TTarget assignable to T (throws if there is 0 or more than
// one mapper, as this would be an implementation error)
dynamic mapper = mappers.Single(x => mapperBaseType.IsAssignableFrom(x.GetType()));
// The method must implemented implicitly.
// A workaround would be to use a wrapper (IMapperWrapper<TSource, out TTarget>)
// that implements the method implicitly and invokes the mapper's method
// without using dynamic
return mapper.Extract((dynamic)source);
}
}

Getting generic value from fieldinfo throws exception: "Late bounds operation cannot be performed..."

I'm trying to get an instance value of a generic type from a static field inside a generic class, and it throws this exception:
Late bound operations cannot be performed on fields with types for which Type.ContainsGenericParameters is true
public class ManagerTemplate<Q, T> : IObjectManager
where T : Filmation.Runtime.Engine.ObjectId, new( )
where Q : ManagerTemplate<Q, T>, new( ) {
public readonly static Q Instance = new Q( ); <---- STATIC FIELD
}
private static void FindManagers( ) {
var IObjectManagerType = typeof( IObjectManager );
var managers = IObjectManagerType.Assembly
.GetTypes( )
.Where( t => !t.IsAbstract && t.GetInterfaces().Any( i => i == IObjectManagerType) );
foreach (var manager in managers) {
var fi = manager.GetField( "Instance" );
var instance = fi.GetValue( null ); <--- EXCEPTION
}
}
I have tried to use GetGenericTypeDefinition, but continues throwing the exception.
I have searched in google, but I have not found how it can be done...
Anyone knows how it can be done?
EDIT: The same using a static property
This is the workaround that I have implemented, (though I'd like to know if it can be done using reflection):
public static Q Instance { get; private set; }
static ManagerTemplate( ) {
Instance = new Q( );
Environment.Managers.Add( Instance );
}
You cannot get the value of public readonly static Q Instance = new Q( ); from the Generic Type Definition ManagerTemplate<Q, T>, simply because there is no concrete type for Q.
How do you get an instance of the generic type definition Q if you do not yet know what the concrete type for Q is? Simple: You can't.
Now... if what you want to get is an instance of a type that descends from ManagerTemplate<Q, T> where the generic type parameter Q is defined, then you actually want to exclude Generic Type Parameters from your search.
private static IEnumerable<IObjectManager> FindManagers()
{
Type type = typeof(IObjectManager);
IEnumerable<Type> managers = type.Assembly
.GetTypes()
.Where(t => !t.IsAbstract && t.GetInterfaces().Contains(type));
foreach (Type manager in managers)
{
var fi = manager.GetField("Instance", BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy);
if (fi != null &&
!fi.FieldType.IsGenericParameter &&
type.IsAssignableFrom(fi.FieldType))
{
yield return (IObjectManager) fi.GetValue(null);
}
}
}
This will get you all the "Managers" defined in all classes that descend from ManagerTemplate<Q, T> that have defined what the type Q is.
The problem is that you are trying to get the Instance field from an unbound generic type, that is, a generic type with unspecified type arguments. An unbound type cannot be instantiated or its methods be called. You need a bound generic type with all the type parameters specified, but consider that each different concrete bound type won't share static fields. For example ManagerTemplate<Class1, Class2> will return a different Instance that ManagerTemplate<Class1, Class3>. All instances of ManagerTemplate<Class1, Class2> will share static fields, though.
You can use reflection to bind type arguments to unspecified type parameters of unbound generic types with Type.MakeGenericType. You will need to provide type arguments to your FindManagers class:
private static void FindManagers<Q,T>( ) {
var IObjectManagerType = typeof( IObjectManager );
var managers = IObjectManagerType.Assembly
.GetTypes( )
.Where( t => !t.IsAbstract && t.GetInterfaces().Any( i => i == IObjectManagerType) );
foreach (var manager in managers) {
var concreteType = manager.MakeGenericType(typeof(Q), typeof(T));
var fi = concreteType.GetField( "Instance" );
var instance = fi.GetValue( null );
}
}
I would solve the problem like the following way. Let's start from the code, and I will then explain why the code:
public interface IObjectManager {
}
public abstract class ObjectManager: IObjectManager {
static IEnumerable<IObjectManager> ManagerInstancesIterator() {
foreach(var managerType in managerTypes) {
var info=managerType.BaseType.GetField("Instance");
var instance=info.GetValue(null) as IObjectManager;
yield return instance;
}
}
public static IObjectManager[] FindManagerInstances() {
return ManagerInstancesIterator().ToArray();
}
public ObjectManager() {
managerTypes.Add(this.GetType());
}
static readonly HashSet<Type> managerTypes=new HashSet<Type>();
}
public class ManagerTemplate<Q, T>: ObjectManager
where T: new()
where Q: ManagerTemplate<Q, T>, new() {
public readonly static Q Instance=new Q();
}
public class CuriousClass<T>
: ManagerTemplate<CuriousClass<T>, T> where T: new() {
}
the test code:
public static partial class TestClass {
public static void TestMethod() {
var instanceByObject=CuriousClass<object>.Instance;
var instanceByInt32=CuriousClass<int>.Instance;
var instances=ObjectManager.FindManagerInstances();
}
}
Note the constraint of Filmation.Runtime.Engine.ObjectId is removed temporarily, you can add it back as your requirement.
You are using the curiously recurring template pattern, and the consumers' code in fact does not have a way to instantiate ManagerTemplate<Q, T> without implementing a concrete class which inherits from ManagerTemplate<Q, T>.
For the reason you encountered the exception, is pointed out by other answers. The class ManagerTemplate<Q, T> is an open generic class, that is, unless you specified the type arguments, the generic class is just a definition; it doesn't have a type instance.
The close generic type would be in the runtime types cache, and doesn't exist in the assembly. So the easiest way to get the type instances which are really used to instantiate objects, is store them in a collection. But as ManagerTemplate<Q, T> is generic, if we declare a collection in its class declaration, then there would be different collections for each close generic type. This is the reason why a base class ObjectManager. But, we don't want itself be instantiated, so it's abstract.
For why managerTypes.Add(this.GetType()); is in an instance constructor instead of a class initializer, the reason is simple, a static constructor doesn't let us know what type is this.
So in conclution, I consider a design in this way as a practical solution.

Multiple generic types in same list and calling their methods

I'm making an object validation framework in my spare time to learn a few things and maybe use it for some school projects.
I have my generic Rule class, which looks something like this :
class Rule<T>
{
string propertyName;
Func<T, bool> ruleLambda;
bool IsBroken(T value)
{
return ruleLambda(value);
}
}
An object that would be validated would look a bit like this :
class Example
{
List<Rule<?>> MyRules; // can take all types of rules
List<Rule<T>> Validate<T>(string propertyName, T value)
{
List<Rule<T>> brokenRules = new List<Rule<T>>();
foreach (Rule rule in MyRules.Where(r => r.propertyName == propertyName))
{
if (rule.IsBroken(value))
brokenRules.Add(rule);
}
return brokenRules;
}
}
Where the T value argument would be the value of one of the Example class's properties, which can be of any type.
The Validate<T> method is called whenever a property is set.
The problem lies with the class's list of rules. Specifically the List<Rule<?>> line above. I want to store all the rules for a given class in the same list.
Alas, C# doesn't have a wildcard for generic types like in Java.
How should I do this?
A non-generic interface or base class utilizing objects instead of T could work, but how would I call the generic Rule's IsBroken method and not the non-generic one?
I would store your rules as object inside the Example class and use Enumerable.OfType<T> to find the matching rules for a given type:
class Example
{
private List<object> rules;
List<Rule<T>> Validate<T>(string propertyName, T value)
{
return this.rules.OfType<Rule<T>>()
.Where(r => r.PropertyName == propertyName && r.IsBroken(value))
.ToList();
}
}
In cases where I've needed something like this, I use interfaces or non-generic base classes. For example, you could create an interface:
public interface IRule
{
//non-generic properties & methods
}
public class Rule<T> : IRule
{
//implementation
}
then create a list of the interfaces:
private List<IRule> MyRules;
If you want to make converting from the interface to the generic easy, you could add an extension method:
public static Rule<T> ToGeneric<T>(this IRule rule)
{
return rule as Rule<T>;
}
I've tried a few things and I've found something that works pretty well for my needs. I have Rule<T> inherit from a base abstract rule class, with a generic IsBroken method:
abstract class Rule
{
string propertyName;
Func<object, bool> objectRule;
bool IsBroken<T>(T value)
{
Rule<T> rule = this as Rule<T>;
if (rule == null)
return objectRule(value);
return rule.IsBroken(value);
}
}
As you can see, I try to convert the base class to its generic counterpart using the generic type parameter in the IsBroken method.
Also, when creating a Rule<T> instance, I send a Func<object, bool> to its base class protected constructor:
public Rule(string propertyName, Func<T, bool> ruleLambda)
: base(propertyName, ConvertToObjectFunc(ruleLambda))
{
}
With the conversion method looking like this:
static Func<object, bool> ConvertToObjectFunc(Func<T, bool> func)
{
return new Func<object, bool>(o => func((T)o));
}
However, if it can't cast o to type T, it crashes. So I wrote this... thing:
static Func<object, bool> ConvertToObjectFunc(Func<T, bool> func)
{
return new Func<object, bool>
(
o =>
{
try
{
T obj = (T)o;
return func(obj);
}
catch { return true; } // rule is broken by default
}
);
}
It's pretty ugly, but it works. Hope this can help anybody else.

Categories