This is what I am trying to get
(IList<Foo>)listPropertyInfo.GetValue(item)
This is how I get Foo type
listPropertyInfo.GetValue(item).GetType().GenericTypeArguments[0]
This is what I tried but couldn't make it successfully
Convert.ChangeType(listPropertyInfo.GetValue(item), IList<listPropertyInfo.GetValue(item).GetType().GenericTypeArguments[0]>)
and also this;
((typeof(IList<>).MakeGenericType(listPropertyInfo.GetValue(item).GetType().GenericTypeArguments.Single())))(listPropertyInfo.GetValue(item))
this is method where I am trying to implement
public static void trigger(IList<T> result)
{
foreach (var item in result)
{
foreach (var listPropertyInfo in typeof(T).GetProperties().ToList().FindAll(x => x.PropertyType.Name == typeof(IList<>).Name))
{
trigger((IList<Foo>)listPropertyInfo.GetValue(item));
}
}
}
I solved like this;
IList targetList = (IList)listPropertyInfo.GetValue(item);
Type foo = targetList.GetType().GenericTypeArguments.Single();
Type unboundGenericType = typeof(READ<>);
Type boundGenericType = unboundGenericType.MakeGenericType(foo);
MethodInfo doSomethingMethod = boundGenericType.GetMethod("trigger");
object instance = Activator.CreateInstance(boundGenericType);
doSomethingMethod.Invoke(instance, new object[] { targetList, f, properties });
If you use IList notation, Foo must be defined at compile time, you can't use expression that evaluates at runtime for Foo.
After reading your comments and and the code i would argue you are trying to do it at the wrong spot.
Here an example of how you could do this
public class MyGeneric<T>
{
public static void trigger(IList<T> result)
{
// do generic stuff where
// you do not need to know T
}
}
// this class does only explicit Foo related stuff
public class MyNONEGeneric
{
public static void trigger(IList<Foo> list)
{
// do some
}
}
class Program
{
static void Main(string[] args)
{
PersistentGenericBag<Foo> magicBag = myMagic<Foo>();
// call your generic which do some general list related stuff
MyGeneric<Foo>.trigger(list);
// call your none generic which do some foo related stuff
MyNONEGeneric.trigger(list);
}
}
like you can see i did some sort of "separation of concerns" / "single responsibility principle" here.
Every thing does only "one" thing. so if you are in need to change something you will know exactly where.
Also if you are working in a Team you can tell Person A to do the MyGeneric<T> and Person B to do the MyNONEGeneric
Related
Following this question, it is possible to create a type and an instance form it dynamically like this:
var type = typeof(AnimalContext<>).MakeGenericType(a.GetType());
var a_Context = Activator.CreateInstance(type);
Great.
However, what I want to do instead of creating an instance of a determined type with Activator.CreateInstance(type);is to use a dynamic created type to declare a variable, and assign an instance to my dynamically created type.
Kind of:
myDynamicallyCreatedType variableName = figuredTypeInstace;
But I cannot use the created type(var type = typeof(AnimalContext<>).MakeGenericType(a.GetType()); for declarations. Is that possible?
Edit:
Short scenario explanation where the need came up. I need to call a method that will be called from a "topManager", this topManager holds the respective instance of the types type1Manager and type2Manager that implement the same base interface IMyInterface method ImplementedMethod.
What I am trying to do, could be solved with ifs, like this:
private int HandleInstance(Type itemType, //other args) {
if (itemType == Type.type1) {
topManagerInstance.manager1Instance.ImplementedMethod(//args):
}
elseif (itemType == Type.type2) {
topManagerInstance.manager2Instance.ImplementedMethod(//args):
}
...not meaningful code
{
But, I was wondering if it could be solved handling types to avoid the ifs, like (caps used to spot the key of the question out, not to shout):
private int HandleInstance(Type itemType, //other args) {
Type managerType = itemType == Type.type1 ? typeof(manager1Type) :
typeof(manager2Type);
Type[] managerTypeArray = { managerType, typeof(int) };
var myDynamicallyCreatedType = typeof(IMyInterface<,>).MakeGenericType(managerTypeArray);
//KEY OF THE QUESTION. THIS IS WHAT I AM ASKING FOR
//assign created variable to dynamic created type to call respective method
myDynamicallyCreatedType variableName = topManagerInstance.type1Manager;
//base type. any type1ManagerType or type2ManagerType to be assigned, as
//they inherit from the same IMyInterface<,>, and the type created is
//generic
variableName.ImplementedMethod(//args):
}
It seems like you're just looking to map an enum value to a function call in a specific implementation. One way to do that is to have a factory class that handles it with a Dictionary used as a map. For example:
Given a setup something like this:
// The enum you use for mapping
public enum Thing
{
Foo,
Bar
}
// The various implementations...
public interface ISomeInterface
{
void SomeMethod();
}
public class Foo : ISomeInterface
{
public void SomeMethod() => Console.WriteLine("Foo method!");
}
public class Bar : ISomeInterface
{
public void SomeMethod() => Console.WriteLine("Bar method!");
}
Now you could have a factory that looks like this:
public class MyThingFactory
{
private Dictionary<Thing, ISomeInterface> _registry;
public MyThingFactory()
{
_registry = new Dictionary<Thing, ISomeInterface>
{
{Thing.Foo, new Foo()},
{Thing.Bar, new Bar()},
};
}
public void RunMethod(Thing thing)
{
if(!_registry.TryGetValue(thing, out var item))
{
throw new ArgumentOutOfRangeException(nameof(thing));
}
item.SomeMethod();
}
}
And call it like this:
// You may want to make this static for performance reasons since you won't recreate
// the dictionary every time
var factory = new MyThingFactory();
factory.RunMethod(Thing.Foo);
factory.RunMethod(Thing.Bar);
//Output:
//Foo method!
//Bar method!
I am trying to define an extension method that can return an object of a type defined by the call.
Desired Use: Cat acat = guy.GiveMeYourPet<Cat>();
Attempted implementation
I have no trouble defining generic methods like this:
public static T GiveMeYourPet<T>(Person a) { ... }
Cat acat = GiveMeYourPet<Cat>(guy);
or extension methods like this:
public static Cat GiveMeYourPetCat<P>(this P self) where P : Person, ... { ... }
Cat acat = guy.GiveMeYourPetCat();
But when I try to do what I really want:
public static T GiveMeYourPet<T, P>(this P self) where P : Person, ... { ... }
Cat acat = guy.GiveMeYourPet<Cat>();
The compiler expects GiveMeYourPet() to receive 2 type arguments (even though one is implicitly provided by calling the extension method on the object guy.
What can I do to make this work?
Note that I've also tried reversing the order in which the parameters are defined, but nothing changes:
public static T GiveMeYourPet<P, T>(this P self)
The following call also does not work, because you cannot have a method call in the type specifiation:
Cat acat = guy.GiveMeYourPet<guy.GetType(), Cat>();
The C# compiler type inference is not as sophisticated as you might hope. You have to explicitly specify both types in such a method:
void Main()
{
int i = 0;
bool b = i.GiveMeYourPet<bool, int>();
}
public static class MyExtensions
{
public static T GiveMeYourPet<T, P>(this P self)
{
return default(T);
}
}
If you want to avoid specifying both explicitly (and I wouldn't blame you), you might try to change your method to something like:
public static T GiveMeYourPet<T>(this IPetOwner self)
(with this interface, you shouldn't even need to know what the real type is; if you do, use as or is) Or even:
public static T GiveMeYourPet<T>(this object self)
(and use as or is)
If that's not an option, and the real type of guy (in your example) is not statically known (e.g. you just have him as an object), you'll probably have to use reflection, e.g.:
MethodInfo method = typeof(MyExtensions).GetMethod("GiveMeYourPet");
MethodInfo generic = method.MakeGenericMethod(typeof(Pet), guy.GetType());
generic.Invoke(guy, null);
If something like guy.GiveMeYour.Pet<Cat>(); would work you can build 2 levels similar to code:
public class GiveMeYourBuilder<P>
{
public P Me {get;set;}
public T Pet<T>() : where T: new()
{ return new T();}
}
public static PetExtensions
{
public GiveMeYourBuilder<P>(this P me)
{
return new GiveMeYourBuilder<P> { Me = me;}
}
}
You can't partially specify generic arguments, either they are all inferred or you have to specify them all. In this case, the closest you can get is probably to return an intermediate object which carries the generic Person type the extension method is called on, and define your Get methods on that:
public class GiveContext<T> where T : Person
{
public P MeYourPet<P>() where P : Pet
{
return default(P);
}
}
public static GiveContext<T> Give<T>(this T person) where T : Person
{
return new GiveContext<T>();
}
which you can use like:
var p = new Person();
Cat c = p.Give().MeYourPet<Cat>();
You can't do this, unfortunately. If the compiler can't figure them all out, you need to type out all the type arguments. The C# compiler isn't that smart. dynamic can help though:
public static T GiveMeYourPet<T>(this dynamic self)
{
//in here check that self meets your constraints using is, as, etc.
}
If I have:
void MyMethod(Object obj) { ... }
How can I cast obj to what its actual type is?
If you know the actual type, then just:
SomeType typed = (SomeType)obj;
typed.MyFunction();
If you don't know the actual type, then: not really, no. You would have to instead use one of:
reflection
implementing a well-known interface
dynamic
For example:
// reflection
obj.GetType().GetMethod("MyFunction").Invoke(obj, null);
// interface
IFoo foo = (IFoo)obj; // where SomeType : IFoo and IFoo declares MyFunction
foo.MyFunction();
// dynamic
dynamic d = obj;
d.MyFunction();
I don't think you can (not without reflection), you should provide a type to your function as well:
void MyMethod(Object obj, Type t)
{
var convertedObject = Convert.ChangeType(obj, t);
...
}
UPD:
This may work for you:
void MyMethod(Object obj)
{
if (obj is A)
{
A a = obj as A;
...
}
else if (obj is B)
{
B b = obj as B;
...
}
}
How about
JsonConvert.DeserializeObject<SomeType>(object.ToString());
You could use also Pattern Matching
void MyMethod(Object obj) {
if(obj is SomeType myVar){
myVar.MyFunction();
}
}
If your MyFunction() method is defined only in one class (and its descendants), try
void MyMethod(Object obj)
{
var o = obj as MyClass;
if (o != null)
o.MyFunction();
}
If you have a large number in unrelated classes defining the function you want to call, you should define an interface and make your classes define that interface:
interface IMyInterface
{
void MyFunction();
}
void MyMethod(Object obj)
{
var o = obj as IMyInterface;
if (o != null)
o.MyFunction();
}
In my case AutoMapper works well.
AutoMapper can map to/from dynamic objects without any explicit configuration:
public class Foo {
public int Bar { get; set; }
public int Baz { get; set; }
}
dynamic foo = new MyDynamicObject();
foo.Bar = 5;
foo.Baz = 6;
Mapper.Initialize(cfg => {});
var result = Mapper.Map<Foo>(foo);
result.Bar.ShouldEqual(5);
result.Baz.ShouldEqual(6);
dynamic foo2 = Mapper.Map<MyDynamicObject>(result);
foo2.Bar.ShouldEqual(5);
foo2.Baz.ShouldEqual(6);
Similarly you can map straight from dictionaries to objects, AutoMapper will line up the keys with property names.
more info https://github.com/AutoMapper/AutoMapper/wiki/Dynamic-and-ExpandoObject-Mapping
Cast it to its real type if you now the type for example it is oriented from class named abc.
You can call your function in this way :
(abc)(obj)).MyFunction();
if you don't know the function it can be done in a different way. Not easy always. But you can find it in some way by it's signature. If this is your case, you should let us know.
If multiple types are possible, the method itself does not know the type to cast, but the caller does, you might use something like this:
void TheObliviousHelperMethod<T>(object obj) {
(T)obj.ThatClassMethodYouWantedToInvoke();
}
// Meanwhile, where the method is called:
TheObliviousHelperMethod<ActualType>(obj);
Restrictions on the type could be added using the where keyword after the parentheses.
Another option is to serialise it and then deserialise it as the object you want.
JsonConvert.DeserializeObject<OtherType>(JsonConvert.SerializeObject(obj));
Implement an interface to call your function in your method
interface IMyInterface
{
void MyinterfaceMethod();
}
IMyInterface MyObj = obj as IMyInterface;
if ( MyObj != null)
{
MyMethod(IMyInterface MyObj );
}
Casting to actual type is easy:
void MyMethod(Object obj) {
ActualType actualyType = (ActualType)obj;
}
I'm trying to figure out how I can make a Generics call take a variable for the Type. In the call below it take a type "DAL.Account" and works fine.
var tst = ctx.GetTable<DAL.Account>().Where(t => t.Sbank == "000134");
I want to change that so that I can pass a variable in place of the "DAL.Account". Something like this but I know that won't work as you can't pass property as a Type.
ctx.GetTable<Criteria.EntityType>().Where(LinqToSQLHelper.BuildWhereStatement(Criteria.StateBag), Criteria.StateBag.Values.ToArray())
Below is the shell pieces of code I think explains what I'm trying to do. Generics is not my strong suit so I'm looking for some help. Is there anyway that I can make this happen?
//Stores a "Type" that indicates what Object is a Criteria for.
public class AccountCriteria : IGeneratedCriteria
{
...
public Type EntityType
{
get {return typeof(DAL.Account);}
}
}
//I have added a function to the DataContext called "GetTable"
// And then used it as an example in a Console App to test its functionality.
public class ADRPDataContext : NHibernateDataContext
{
...
public CodeSmith.Data.NHibernate.ITable<T> GetTable<T>() where T : EntityBase
{
var tb = new CodeSmith.Data.NHibernate.Table<T>(this);
return tb;
}
}
// console application that uses DataContext.GetTable
class Program
{
static void Main(string[] args)
{
using (var ctx = new ADRPDataContext())
{
var tst = ctx.GetTable<DAL.Account>().Where(t => t.Sbank == "000134");
}
}
}
//ExistsCommand class that uses the EntityType property of the Critera to generate the data.
public class ExistsCommand
{
private IGeneratedCriteria Criteria { get; set; }
protected override void DataPortal_Execute()
{
using (var ctx = new DC.ADRPDataContext())
{
//This was my first attempt but doesn't work becuase you can't pass a property in for a Type.
//But I can figure out how to write this so that it will work.
Result = ctx.GetTable<Criteria.EntityType>().Where(LinqToSQLHelper.BuildWhereStatement(Criteria.StateBag), Criteria.StateBag.Values.ToArray()).Count() > 0;
}
}
}
You are looking to instantiate a generic type. Some info can be found here
This is a simple example demonstrating how to instantiate a List with a capacity of 3. Here is a method that you can call to create a generic when you don't know the type:
public static Object CreateGenericListOfType(Type typeGenericWillBe)
{
//alternative to the followin:
//List<String> myList = new List<String>(3);
//build parameters for the generic's constructor (obviously this code wouldn't work if you had different constructors for each potential type)
object[] constructorArgs = new Object[1];
constructorArgs[0] = 3;
//instantiate the generic. Same as calling the one line example (commented out) above. Results in a List<String> with 3 list items
Type genericListType = typeof(List<>);
Type[] typeArgs = { typeGenericWillBe };
Type myNewGeneric = genericListType.MakeGenericType(typeArgs);
object GenericOfType = Activator.CreateInstance(myNewGeneric, constructorArgs);
return GenericOfType;
}
And here is some sample code that will show you the example method works:
List<String> Strings = (List<String>)InstantiateGenericTypeWithReflection.CreateGenericListOfType(typeof(String));
//demonstrate the object is actually a List<String> and we can do stuff like use linq extensions (isn't a good use of linq but serves as example)
Strings.Add("frist");
Strings.Add("2nd");
Strings.Add("tird");
Console.WriteLine("item index 2 value: " + Strings.Where(strings => strings == "2").First());
In your example, replace your GetTable<Criteria.EntityType>() with CreateGenericTableOfType(Criteria.EntityType). This will return a generic table of whatever type you pass in. You will of course need to implement the method properly (handle constructor args, change List to Table etc).
I think you need to change the way you're doing this slightly, and instead use generics instead of the EntityType property. Perhaps something along the lines of the following:
// Create an abstract class to be used as the base for classes that are supported by
// ExistsCommand and any other classes where you need a similar pattern
public abstract class ExtendedCriteria<T> : IGeneratedCriteria
{
public ExistsCommand GetExistsCommand()
{
return new ExistsCommand<T>(this);
}
}
// Make the non-generic ExistsCommand abstract
public abstract class ExistsCommand
{
protected abstract void DataPortal_Execute();
}
// Create a generic sub-class of ExistsCommand with the type parameter used in the GetTable call
// where you were previously trying to use the EntityType property
public class ExistsCommand<T> : ExistsCommand
{
protected override void DataPortal_Execute()
{
using (var ctx = new DC.ADRPDataContext())
{
Result = ctx.GetTable<T>().Where(LinqToSQLHelper.BuildWhereStatement(Criteria.StateBag), Criteria.StateBag.Values.ToArray()).Count() > 0;
}
}
}
// Derive the AccountCriteria from ExtendedCriteria<T> with T the entity type
public class AccountCriteria : ExtendedCriteria<DAL.Account>
{
...
}
I find myself (too) often using a construct like the following:
class MyClass
{
public TypeA ObjectA;
public TypeB ObjectB;
public TypeC ObjectC;
public List<TypeD> ListOfObjectD = new List<TypeD>();
public void DoSmth()
{
return SomeConstruct(
/*...*/
new Setter<TypeA>(a => ObjectA = a), // these are the
new Setter<TypeB>(b => ObjectB = b), // things I'm trying
new Setter<TypeC>(c => ObjectC = c), // to make shorter
new Setter<TypeD>(d => ListOfObjectD.Add(d)),
/*...*/
);
}
}
class Setter<T>
{
public Action<T> Action;
public Setter(Action<T> action)
{
Action = action;
}
}
Is there any way for the Setter class to infer the type of the Action and create the standard (T obj) => Member = obj Action by only passing the Member in some way? I'm thinking of something like:
new Setter(ObjectA)
which of course is not valid syntax, but should give you an idea what I'm trying to achieve. I'm using this construct literally hundreds of time in my code, so the code
saved by this small change would be tremendous.
Edit: Added the TypeD example. The part
new Setter<TypeD>(d => ListOfObjectD.Add(d))
can be simplified to
new Setter<TypeD>(ListOfObjectD.Add)
which is awesome because it cuts from the redundant code. If only <TypeD> could also be inferred it would be perfect. I'm looking for something like this for the others.
#Lazarus - basically the purpose is to return setters, so other objects can set certain members of the class (or it can do other stuff defined in the Action) without accessing the class itself, only the Setter object. The full list of reasons is long and convoluted, but the structuring of the program works like a charm and I doubt needs changing (the example of course is simplified and doesn't really make sense as is).
Edit 2: I found a good way to simplify things for List's:
static class SetterHelper
{
public static Setter<T> GetSetter<T>(this List<T> list)
{
return new Setter<T>(list.Add);
}
}
Now I can just use this:
ListOfObjectD.GetSetter()
which works perfectly! why can't I do the same for T directly? I tried this:
static class SetterHelper
{
public static Setter<T> GetSetter<T>(this T item)
{
return new Setter<T>(t => item = t); // THIS DOESN'T SET THE PASSED MEMBER
}
}
Of course it won't work as intended because it will set item, but not the passed member. I tried adding ref as (ref this T item) but it won't compile :(... It would have been perfect.
Best I can offer you is the following syntax:
Setter.For( () => ObjectA );
using this helper class
static class Setter
{
public static Setter<T> For<T>(Expression<Func<T>> e)
{
ParameterExpression[] args = { Expression.Parameter(((e.Body as MemberExpression).Member as FieldInfo).FieldType) };
Action<T> s = Expression.Lambda<Action<T>>(Expression.Assign(e.Body, args[0]), args).Compile();
return new Setter<T>(s);
}
}