If a class has a property that is of a generic type (Like Thingus<T> below), is it possible to use a null instance of that class without specifying the type of the generically-typed property for that object?
using System;
public class Program
{
public static void Main()
{
DoThing(new Thingus<int>
{
Name = "Integer thingus",
Something = 42
});
//Is there a way to make this function work without the function on line 19?
//If thingus is null then I don't care what the Type is for Something.
//If not, does the type used in the function on line 19 matter for performance at all?
DoThing();
}
public static void DoThing(Thingus<string> thingus = null) => DoThing<string>(thingus);
public static void DoThing<T>(Thingus<T> thingus)
{
if(thingus is null)
{
Console.WriteLine("Oh look! The thingus is null!");
}
else
{
Console.WriteLine($"Thingus's Something is {thingus.Something}");
}
}
}
public class Thingus<T>
{
public string Name { get; set; }
public T Something { get; set; }
}
To see why it is probably impossible, consider this code snippet
public static void DoThing<T>(Thingus<T> thingus)
{
Console.WriteLine(typeof(T));
}
If you write DoThing(null), there is no hints that which type T you want to use, so it is impossible for the compiler to make it works because with just DoThing(null) you are providing not enough information for the compiler.
You don't need to specify the type parameter on your first call, because the compiler can infer it from the int on the type parameter in the argument. In your second method, it can't infer that, because you want to send null.
You can drop the method you want to drop, and call your generic method with some irrelevant type parameter to satisfy the compiler:
DoThing<Thingus<int>>(null);
I have the following types:
public abstract class Game<TRules>
where TRules : new()
{
public TRules Rules { get; set; } = new TRules();
}
public class Cricket : Game<CricketRules>
{
}
public class CricketRules
{
public string SomeRule { get; set; }
}
I also have an extension method that helps set the rules property:
public static class GameExtensions
{
public static void SetRules<TGame, TRules>(this TGame game, Action<TRules> setter)
where TGame : Game<TRules>
where TRules : new()
{
setter(game.Rules);
}
}
and I'm able to call the extension method:
new Cricket().SetRules<Cricket, CricketRules>(r => { r.SomeRule = "rule"; });
but I get an error when I omit specifying the type parameters:
new Cricket().SetRules(r => { r.SomeRule = "rule"; }); // doesn't compile
I'd have expected the extension method to infer both TGame as Cricket and TRules as CricketRules in this case due to the constraint TGame : Game<TRules> on the method.
Is there any way to avoid passing the type parameters explicitly when calling the extension method?
Note: I've seen some SO answers that suggest (for slightly different scenarios) splitting the extension method into two (in different classes) each taking a single type parameter but am not able to figure out a similar approach that would work in this case.
You can specify the type in the lambda:
new Cricket().SetRules((CricketRules r) => { r.SomeRule = "rule"; });
Normally (or rather, almost always) you'd omit the type name. People omit it so often that people forget that you can put the type name there... :)
I have a situation where in, I would like to convert an Expression<Func<BaseType,object>> to Expression<Func<DerievedType,object>>
I am also open to other solutions as well for this particular scenario.
To demonstrate the problem, i have base class as following
public class PersonBase
{
public string Name{get;set;}
public virtual void Save()
{
Dummy.Method1(this,x=>x.Name);
}
}
Derieved Class is defined as
public class Student:PersonBase
{
public string School{get;set;}
}
The Dummy class and associated methods are defined as
public class Dummy
{
public static void Method1<TDestination>(TDestination value,params Expression<Func<TDestination,object>>[] selector)
{
var destinationType = value.GetType();
var selectorType = selector.GetType();
Console.WriteLine("Destination Type : " + destinationType.ToString());
Console.WriteLine("Selector Type : " +selectorType.ToString());
var FinalMethodToCallInfo = typeof(Dummy).GetMethod("FinalMethodToCall", BindingFlags.Public | BindingFlags.Static);
var FinalMethodToCallMethod = FinalMethodToCallInfo.MakeGenericMethod(destinationType);
FinalMethodToCallMethod.Invoke(null, new object[] { selector });
}
public static void FinalMethodToCall<TDestination>(params Expression<Func<TDestination,object>>[] selector)
{
Console.WriteLine("Finally here");
}
}
The whole example is demonstrated in the Fiddle here.
Since the destinationType in Method1 is of Type Student and selectorType is of type Expression>, I get an exception when i attempt to invoke the FinalMethodToCall using reflection.
Object of type 'System.Linq.Expressions.Expression`1[System.Func`2[PersonBase,System.Object]][]' cannot be converted to type 'System.Linq.Expressions.Expression`1[System.Func`2[Student,System.Object]][]'.
I am slightly lost here. One solution I could think of was to use ExpressionVisitor to replace the Expression Parameter Type from BaseClass to DerievedType.
But I was curious to know why, when calling the method from Base (and passing expression), I was pointing to two different types (Derieved and Base). Could someone guide me in understanding this behavior and also if there is a better solution than using ExpressionVisitor to replace the Parameter Type ?
PS: I cannot change signature of my Save Method.
I have made few changes to generic methods as below.
Update PersonBase and make Save method to explicitly declare T.
public class PersonBase
{
public string Name{get;set;}
public virtual void Save<T>() where T : PersonBase
{
Dummy.Method1<T>(this,x=>x.Name);
}
}
Update Method1's first parameter to be Object like below.
public static void Method1<TDestination>(Object value,params Expression<Func<TDestination,object>>[] selector)
And call your Save with explicitly passing generic value like as follow.
(new Student{Name="anu"}).Save<Student>();
I need to get the type of a property that will only be known at run time and pass this as a type parameter for a generic method. For example:
PropertyInfo prop = Bar.GetProperty("Property1");
//"type 'prop' could not be found" error
Foo<prop.PropertyType>();
void Foo<T>()
{
//Stuff
}
class Bar
{
string Property1{get;set;}
}
The type of Bar.Property1 will not be known at compile time, so I can't do Foo<string>();. It will compile and run correctly if I use Foo<dynamic>(); but I'm not convinced that's the best way to go, and I'd like to know if there is a way to do it using an older framework.
Hopefully, this more complete example will make my intentions clearer:
public void Map(TInType inObject, TOutType outObject)
{
//propertyIn, propertyOut, and converter are all strings identifying the properties/methods to be used from the inObject/Type outObject/Type.
SetPropertyValues<dynamic, dynamic>(inObject, outObject, propertyIn, propertyOut, converter);
}
private void SetPropertyValues<TPropIn,TPropOut>(TInType fromObject, TOutType toObject, string propertyIn, string propertyOut, string converter)
{
PropertyInfo prop1 = typeof(TInType).GetProperty(propertyIn);
MethodInfo converterMethod = typeof(TInType).GetMethod(converter);
PropertyInfo prop2 = typeof(TOutType).GetProperty(propertyOut);
prop2.SetValue(
toObject,
CopyPropertyValue<TPropIn, TPropOut>((TPropIn)prop1.GetValue(fromObject, null), p => (TPropOut)converterMethod.Invoke(fromObject, new object[] { p })),
null);
}
private TPropOut CopyPropertyValue<TPropIn, TPropOut>(TPropIn InPropValue, Func<TPropIn, TPropOut> converterFunction)
{
return converterFunction(InPropValue);
}
I'm open to any other suggestions anyone may have, or that the code should be taken out back and shot, but my original question is still the one I'm most interested in.
You can use MakeGenericMethod, performance is actually quite reasonable and allows you to explicitly define what you are calling with what, so reduces the overhead.
So something like the following, the Invoker would call the explicit method / class you need, and the helper actually invokes the generic call.
public class GenericHelper
{
public static void DoSomethingGeneric(GenericInvokerParameters parameters)
{
var targetMethodInfo = typeof(GenericInvoker).GetMethod("DoSomethingGeneric");
var genericTargetCall = targetMethodInfo.MakeGenericMethod(parameters.InvokeType);
genericTargetCall.Invoke(new GenericInvoker(), new[] { parameters });
}
}
public class GenericInvoker
{
public void DoSomethingGeneric<T>(GenericInvokerParameters parameters)
{
//Call your generic class / method e.g.
SomeClass.SomeGenericMethod<T>(parameters.SomeValue);
}
}
public class GenericInvokerParameters
{
public GenericInvokerParameters(Type typeToInvoke, string someValue)
{
SomeValue = someValue;
InvokeType = typeToInvoke;
}
public string SomeValue { get; private set; }
public Type InvokeType { get; private set; }
}
Don't see anything bad in dynamic.
Use it.
EDIT
Till you're not going to call that method with high frequency, where the reflection could bit it from performance perspective, I would prefer dynamic
Foo should not be generic if you are not using it generically. Just make it operate on type Object instead of T.
I am working on rewriting my fluent interface for my IoC class library, and when I refactored some code in order to share some common functionality through a base class, I hit upon a snag.
Note: This is something I want to do, not something I have to do. If I have to make do with a different syntax, I will, but if anyone has an idea on how to make my code compile the way I want it, it would be most welcome.
I want some extension methods to be available for a specific base-class, and these methods should be generic, with one generic type, related to an argument to the method, but the methods should also return a specific type related to the particular descendant they're invoked upon.
Better with a code example than the above description methinks.
Here's a simple and complete example of what doesn't work:
using System;
namespace ConsoleApplication16
{
public class ParameterizedRegistrationBase { }
public class ConcreteTypeRegistration : ParameterizedRegistrationBase
{
public void SomethingConcrete() { }
}
public class DelegateRegistration : ParameterizedRegistrationBase
{
public void SomethingDelegated() { }
}
public static class Extensions
{
public static ParameterizedRegistrationBase Parameter<T>(
this ParameterizedRegistrationBase p, string name, T value)
{
return p;
}
}
class Program
{
static void Main(string[] args)
{
ConcreteTypeRegistration ct = new ConcreteTypeRegistration();
ct
.Parameter<int>("age", 20)
.SomethingConcrete(); // <-- this is not available
DelegateRegistration del = new DelegateRegistration();
del
.Parameter<int>("age", 20)
.SomethingDelegated(); // <-- neither is this
}
}
}
If you compile this, you'll get:
'ConsoleApplication16.ParameterizedRegistrationBase' does not contain a definition for 'SomethingConcrete' and no extension method 'SomethingConcrete'...
'ConsoleApplication16.ParameterizedRegistrationBase' does not contain a definition for 'SomethingDelegated' and no extension method 'SomethingDelegated'...
What I want is for the extension method (Parameter<T>) to be able to be invoked on both ConcreteTypeRegistration and DelegateRegistration, and in both cases the return type should match the type the extension was invoked on.
The problem is as follows:
I would like to write:
ct.Parameter<string>("name", "Lasse")
^------^
notice only one generic argument
but also that Parameter<T> returns an object of the same type it was invoked on, which means:
ct.Parameter<string>("name", "Lasse").SomethingConcrete();
^ ^-------+-------^
| |
+---------------------------------------------+
.SomethingConcrete comes from the object in "ct"
which in this case is of type ConcreteTypeRegistration
Is there any way I can trick the compiler into making this leap for me?
If I add two generic type arguments to the Parameter method, type inference forces me to either provide both, or none, which means this:
public static TReg Parameter<TReg, T>(
this TReg p, string name, T value)
where TReg : ParameterizedRegistrationBase
gives me this:
Using the generic method 'ConsoleApplication16.Extensions.Parameter<TReg,T>(TReg, string, T)' requires 2 type arguments
Using the generic method 'ConsoleApplication16.Extensions.Parameter<TReg,T>(TReg, string, T)' requires 2 type arguments
Which is just as bad.
I can easily restructure the classes, or even make the methods non-extension-methods by introducing them into the hierarchy, but my question is if I can avoid having to duplicate the methods for the two descendants, and in some way declare them only once, for the base class.
Let me rephrase that. Is there a way to change the classes in the first code example above, so that the syntax in the Main-method can be kept, without duplicating the methods in question?
The code will have to be compatible with both C# 3.0 and 4.0.
Edit: The reason I'd rather not leave both generic type arguments to inference is that for some services, I want to specify a parameter value for a constructor parameter that is of one type, but pass in a value that is a descendant. For the moment, matching of specified argument values and the correct constructor to call is done using both the name and the type of the argument.
Let me give an example:
ServiceContainerBuilder.Register<ISomeService>(r => r
.From(f => f.ConcreteType<FileService>(ct => ct
.Parameter<Stream>("source", new FileStream(...)))));
^--+---^ ^---+----^
| |
| +- has to be a descendant of Stream
|
+- has to match constructor of FileService
If I leave both to type inference, the parameter type will be FileStream, not Stream.
I wanted to create an extension method that could enumerate over a list of things, and return a list of those things that were of a certain type. It would look like this:
listOfFruits.ThatAre<Banana>().Where(banana => banana.Peel != Color.Black) ...
Sadly, this is not possible. The proposed signature for this extension method would have looked like:
public static IEnumerable<TResult> ThatAre<TSource, TResult>
(this IEnumerable<TSource> source) where TResult : TSource
... and the call to ThatAre<> fails because both type arguments need to be specified, even though TSource may be inferred from the usage.
Following the advice in other answers, I created two functions: one which captures the source, and another which allows callers to express the result:
public static ThatAreWrapper<TSource> That<TSource>
(this IEnumerable<TSource> source)
{
return new ThatAreWrapper<TSource>(source);
}
public class ThatAreWrapper<TSource>
{
private readonly IEnumerable<TSource> SourceCollection;
public ThatAreWrapper(IEnumerable<TSource> source)
{
SourceCollection = source;
}
public IEnumerable<TResult> Are<TResult>() where TResult : TSource
{
foreach (var sourceItem in SourceCollection)
if (sourceItem is TResult) yield return (TResult)sourceItem;
}
}
}
This results in the following calling code:
listOfFruits.That().Are<Banana>().Where(banana => banana.Peel != Color.Black) ...
... which isn't bad.
Notice that because of the generic type constraints, the following code:
listOfFruits.That().Are<Truck>().Where(truck => truck.Horn.IsBroken) ...
will fail to compile at the Are() step, since Trucks are not Fruits. This beats the provided .OfType<> function:
listOfFruits.OfType<Truck>().Where(truck => truck.Horn.IsBroken) ...
This compiles, but always yields zero results and indeed doesn't make any sense to try. It's much nicer to let the compiler help you spot these things.
If you have only two specific types of registration (which seems to be the case in your question), you could simply implement two extension methods:
public static DelegateRegistration Parameter<T>(
this DelegateRegistration p, string name, T value);
public static ConcreteTypeRegistration Parameter<T>(
this ConcreteTypeRegistration p, string name, T value);
Then you wouldn't need to specify the type argument, so the type inference would work in the example you mentioned. Note that you can implement both of the extension methods just by delegation to a single generic extension method with two type parameters (the one in your question).
In general, C# doesn't support anything like o.Foo<int, ?>(..) to infer only the second type parameter (it would be nice feature - F# has it and it's quite useful :-)). You could probably implement a workaround that would allow you to write this (basically, by separating the call into two method calls, to get two places where the type inferrence can be applied):
FooTrick<int>().Apply(); // where Apply is a generic method
Here is a pseudo-code to demonstrate the structure:
// in the original object
FooImmediateWrapper<T> FooTrick<T>() {
return new FooImmediateWrapper<T> { InvokeOn = this; }
}
// in the FooImmediateWrapper<T> class
(...) Apply<R>(arguments) {
this.InvokeOn.Foo<T, R>(arguments);
}
Why don't you specify zero type parameters? Both can be inferred in your sample. If this is not an acceptable solution for you, I'm frequently encountering this problem too and there's no easy way to solve the problem "infer only one type parameter". So I'll go with the duplicate methods.
What about the following:
Use the definition you provide:
public static TReg Parameter<TReg, T>(
this TReg p, string name, T value)
where TReg : ParameterizedRegistrationBase
Then cast the parameter so the inference engine gets the right type:
ServiceContainerBuilder.Register<ISomeService>(r => r
.From(f => f.ConcreteType<FileService>(ct => ct
.Parameter("source", (Stream)new FileStream(...)))));
I think you need to split the two type parameters between two different expressions; make the explicit one be part of the type of a parameter to the extension method, so inference can then pick it up.
Suppose you declared a wrapper class:
public class TypedValue<TValue>
{
public TypedValue(TValue value)
{
Value = value;
}
public TValue Value { get; private set; }
}
Then your extension method as:
public static class Extensions
{
public static TReg Parameter<TValue, TReg>(
this TReg p, string name, TypedValue<TValue> value)
where TReg : ParameterizedRegistrationBase
{
// can get at value.Value
return p;
}
}
Plus a simpler overload (the above could in fact call this one):
public static class Extensions
{
public static TReg Parameter<TValue, TReg>(
this TReg p, string name, TValue value)
where TReg : ParameterizedRegistrationBase
{
return p;
}
}
Now in the simple case where you are happy to infer the parameter value type:
ct.Parameter("name", "Lasse")
But in the case where you need to explicitly state the type, you can do so:
ct.Parameter("list", new TypedValue<IEnumerable<int>>(new List<int>()))
Looks ugly, but hopefully rarer than the simple fully-inferred kind.
Note that you could just have the no-wrapper overload and write:
ct.Parameter("list", (IEnumerable<int>)(new List<int>()))
But that of course has the disadvantage of failing at runtime if you get something wrong. Unfortunately away from my C# compiler right now, so apologies if this is way off.
I would used the solution:
public class JsonDictionary
{
public static readonly Key<int> Foo = new Key<int> { Name = "FOO" };
public static readonly Key<string> Bar = new Key<string> { Name = "BAR" };
IDictionary<string, object> _data;
public JsonDictionary()
{
_data = new Dictionary<string, object>();
}
public void Set<T>(Key<T> key, T obj)
{
_data[key.Name] = obj;
}
public T Get<T>(Key<T> key)
{
return (T)_data[key.Name];
}
public class Key<T>
{
public string Name { get; init; }
}
}
See:
C#: Exposing type safe API over heterogeneous dictionary