I cannot find a way to pass an anonymous type to a generic class as a type parameter.
// this is the class I want to instantiate
public class ExtArrayStore<T> : IViewComponent
{
public IQueryable<T> Data { get; set; }
...
// the creator class
public static class ArrayStoreGenerator
{
public static ExtArrayStore<T> CreateInstance<T>(IQueryable<T> query)
{
return new ExtArrayStore<T>();
}
}
// trying to use this
IQueryable usersQuery= ((from k in bo.usersselect new { userid = k.userid, k.username}).AsQueryable());
var x = ArrayStoreGenerator.CreateInstance(usersQuery);
I am getting;
The type arguments for method ArrayStoreGenerator.CreateInstance(System.Linq.IQueryable)' cannot be inferred from the usage. Try specifying the type arguments explicitly
Is there a way to achieve this? ( I am thinking of Interfaces and returning an interface, but not sure if it would work) can any one help with passing anon types to generics.
usersQuery is being typed as the non-generic IQueryable because you explicitly specify that in the variable's declaration.
Instead, do var usersQuery = .... This will type the variable as IQueryable<TAnon>, which then matches the signature of ArrayStoreGenerator.CreateInstance.
You should define usersQuery as var.
What if you try var usersQuery local variable instead of explicitly specify its type?
Try with ToArray:
var x = ArrayStoreGenerator.CreateInstance(usersQuery.ToArray());
Related
Now I have a SomeClass<T> with a constructor SomeClass(IList<T?> list). But when I use a List<int?> to construct it, the compiler told me:
Cannot resolve constructor
SomeClass(System.Collections.Generic.List<System.Nullable<int>>),
candidates are: SomeClass(System.Collections.Generic.IList<int>)
I find it means that I have to add "struct" to T's base class list to make sure that T is a value type, but why does this happen and how can make this class avoid using only value type as generic parameter?
#canton7 explains why this does not work in a comment.
You cannot solve this with a constructor, as you will have to introduce a new type parameter and constructors cannot declare type parameters. Therefore I suggest using a factory method.
public class SomeClass<T>
{
public IList<T> List { get; private set; }
public static SomeClass<T> Create<U>(IList<Nullable<U>> list)
where U : struct, T
{
return new SomeClass<T> {
List = list
.OfType<T>()
.ToList()
};
}
}
Introducing the type parameter U allows us to add a type constraint that is limited to this method, while the type parameter T of the class remains unconstrained.
Note that a null value does not have a type. Therefore, OfType<T>() filters out nulls.
You can test it like this:
var ints = new List<int?> { 1, 2, null, 3 };
var sut = SomeClass<int>.Create(ints);
foreach (int item in sut.List) {
Console.WriteLine(item);
}
Prints:
1
2
3
I am try to create a common extension method which sorts list of object by a specific property. I am getting the below error for my code.
The type arguments for method Queryable.OrderBy cannot be inferred from the usage. Try specifying the type arguments explicitly.
I tried to find the answer here could not find any suitable answer.
public static IEnumerable<T> OrderByProperty<T>(this IEnumerable<T> list,
string property)
{
return list.AsQueryable().OrderBy(property);
}
Is there anything I am missing here.
For me adding the following using directive resolved it.
using System.Linq.Dynamic.Core;
If you want to use property string name sort data then you can use System.Linq.Dynamic : Github Link
Notice : you have to call AsQueryable because Linq.Dynamic only support IQueryable Type.
Example :
void Main()
{
var datas = new[] { new { id = 3 }, new { id = 2 } };
var result = datas.OrderByProperty("id");
Console.WriteLine(result); //2,3
}
// Define other methods and classes here
public static class MyExtension
{
public static IEnumerable<T> OrderByProperty<T>(this IEnumerable<T> list,string property)
{
return list.AsQueryable().OrderBy(property);
}
}
OrderBy accepts Func<TSource,TKey> as argument, not string: Enumerable.OrderBy Method
I don't see any reason why you would simplify something that is simple enough:
someEnumerable.OrderBy(item => item.Property);
Passing property by string would also require reflection to come into play, so it is really discouraged.
Is there any way to infere the type parameter dynamically so that the type of an object is used as another objects type?
I have a generic type called ObjectPrinter that takes a list of the same type it is of in the constructor. It would be neat to not have to declare the type but just have it infered from the argument.
// This is how i do it. But since myFruits is a list of fruits could not the type Fruit be infered automatically?
List<Fruits> myFruits = GetFruits();
var fruitPrinter = new ObjectPrinter<Fruit>(myFruits);
// Id like to to this
List<Fruits> myFruits = GetFruits();
var fruitPrinter = new ObjectPrinter(myFruits); // and get a ObjectPRinter of type Fruit
Constructors in C# are explicitly not generics - you can't do what you want to do directly. Only member functions can have generic parameters.
However, that tells you what you can do: use a factory function instead of a constructor. Something like this:
public class PrinterFactory {
public static ObjectPrinter CreatePrinter<T>(List<T> things) {
return new ObjectPrinter<T>(things);
}
}
Then you can change your calling code to:
List<Fruit> myFruits = GetFruits();
var fruitPrinter = PrinterFactory.CreatePrinter(myFruits);
And everything should just work.
You can of course put the factory function on whatever class you want.
I have a class which uses generic properties. For example:
class Person
{
public MyGenericProperty<string> Field1
{
get { return field1; }
set { field1 = value; }
}
private MyGenericProperty<string> field1= new MyInheritedGenericProperty<string>("Alan1");
}
I want to use this class with reflection at another class and i have a method like that
public void DoSomethingWithProperty(object sourceobject)
{
foreach (var aProperty in sourceobject.GetType().GetProperties())
{
*if(aProperty.PropertyType == typeof(MyGenericProperty<>))*
{
*var obj = (MyGenericProperty<>)aProperty.GetValue(sourceobject, null);*
}
}
return null;
}
I have two problem
1- How can do type check of generic property. In that example code of if(aProperty.PropertyType == typeof(MyGenericProperty<>)) does not work.
2- T of MyGenericProperty could be any class and how can cast MyGenericProperty class without knowing T by reflection as
var obj = (MyGenericProperty<>)aProperty.GetValue(sourceobject, null);
Thank for helps.
Firstly, it's important to understand that you don't have a "generic property" - there's no such thing. You have a property whose type is a generic type... and that's not the same thing. (Compare that with a generic type or a generic method, each of which is genuinely generic in terms of introducing new type parameters.)
You can test it using this code:
if (aProperty.PropertyType.IsGenericType &&
aProperty.GetGenericTypeDefinition() == typeof(MyGenericProperty<>))
But as for the casting - it depends on what you want to do with the value afterwards. You may want to declare a non-generic base type of MyGenericProperty<> containing all the members which don't depend on the type parameter. I'd typically give that the same name as the generic type (e.g. MyGenericProperty) just without giving it type parameters. Then if you only need one of those members, you can use:
if (aProperty.PropertyType.IsGenericType &&
aProperty.GetGenericTypeDefinition() == typeof(MyGenericProperty<>))
{
var value = (MyGenericProperty) aProperty.GetValue(sourceObject, null);
// Use value
}
But then in that case you could use Type.IsAssignableFrom anyway:
if (typeof(MyGenericProperty).IsAssignableFrom(aProperty.PropertyType))
{
var value = (MyGenericProperty) aProperty.GetValue(sourceObject, null);
// Use value
}
If these hints don't help you, please give more details of what you're trying to do.
I meet this problem when I need to verify some code path in my UT.
I need to convert back to its original type to verify the data field is correctly set.
I abstract the class define and my UT is now in the main function for this example
public interface ITestInterface { };
public class TestClass<T> : ITestInterface
{
public T member { get; set; }
}
public static class Util
{
public static ITestInterface Create<C>(C t)
{
return new TestClass<C> { member = t };
}
public static ITestInterface CreateInstance()
{
return Create(new
{
p1 = 100,
p2 = "string"
});
}
}
class Program
{
static void Main(string[] args)
{
var a = Util.CreateInstance();
var b = a as TestClass<Object>;
// this will be "null" in this example
// So, how can I convert back to its real type?
// And get the "member" data
}
}
I think this example can explain exactly my question and what I want
Please be more patient about:
why you use the anonymous type
why you use interface
why use template class derived from non-generic interface
I would like to say the code is already there, I cannot change it (at least currently)
What I want to do is:
check if that interface is an instance of some class derived from ITestInterface
if it is, i need to convert back to that type, can verify its member data
So please share some solution/idea based on this scenario.
BTW,
Of course I know I am using "Object" in my last statement to convert back to the type is not good(or obviously wrong), but in fact I do not know which other things I can put here. "object" is just an intuitive try. Please share any property way to handle this case ( maybe more than just something which is just used to replace "object" ).
I'm not saying this isn't an XY problem but to answer the question you asked.
If you are in the same scope as your anonymous type, you can use type inference with generics to cast it back to the anonymous type.
In my example below, I create the anonymously typed item before calling Util.Create so that I have an instance of that type in a variable that I can use later. Then I call the generic method GetAsTestClass<T>, which uses type inference, based on the 2nd parameter, to set T to the anonymous type. Then it returns item as TestClass<T>, where T is your anonymous type.
public void TestMethod1()
{
var anonItem = new
{
p1 = 100,
p2 = "string"
};
var a = Util.Create(anonItem);
var b = GetAsTestClass(a, anonItem);
// this will be "null" in this example
// So, how can I convert back to its real type?
// And get the "member" data
var c = b.member;
Assert.AreEqual(100, c.p1);
}
public TestClass<T> GetAsTestClass<T>(ITestInterface item, T silentType)
{
return item as TestClass<T>;
}
Edit:
Your specific requirements appear to rule out the type-safe options. Below are code samples using the non-type safe methods of reflection and dynamics. Note that for the dynamic version to work, you need a reference to Microsoft.CSharp in your project.
var a = Util.Create(new
{
p1 = 100,
p2 = "string"
});
var memberAnon = a
.GetType()
.GetProperty("member")
.GetValue(a);
var p1 = memberAnon
.GetType()
.GetProperty("p1")
.GetValue(memberAnon);
Assert.AreEqual(100, p1);
or the dynamic way
dynamic dynamicVar = a;
Assert.AreEqual(100, dynamicVar.member.p1);