How to specify a typed variable if you do not know the type

I have this extension method for my BusinessObject class:

public static class Extensions { public static T Clone<T>(this T obj) where T: BusinessObject<T>, new() { T newObj = new T(); var props = newObj.Properties; foreach (var p in props) newObj.Properties[p.Name].SetValue(newObj, obj.Properties[p.Name].GetValue(obj)); return newObj; } } 

The content of this method works fine, but I do not have a generic BusinessObject class and a generic equivalent. A lot of my code goes around an instance of a universal version of an object inside a non-shared variable (please do not ask me 20 questions about why). So far I have not had a problem, because when I call this extension method, it expects a general version.

The code that calls the Clone method uses the BusinessObject variable, which contains an instance of the BusinessObject variable. How can I apply a variable to what it really is? In other words:

 Customer cust = new Customer(); // Customer derives from BusinessObject<Customer> var CustomerClone = cust.Clone(); // This works BusinessObject obj = cust; var clone = obj.Clone(); // This doesn't work 

Now, of course, in this example, I know that "obj" is the Client, but in my actual method I do not know that it can be any number of derived types. I can find out which derived type is simple enough just by using GetType (), but how do I apply a variable to this type at runtime?

+4
source share
1 answer

In your case, I would say "lose T " - you are not using anything important that cannot be done in other ways ( Activator.CreateInstance , for example). You could offer two APIs - one universal, one not common to provide convenient casting. For instance:

 BusinessObject newObj = (BusinessObject)Activator.CreateInstance(obj.GetType()); 

This is also very important, because the T you want is not really an ad T , and specific T Meaning: if you have SuperCustomer : Customer , but put it in the Customer variable and then call Clone , you want a new SuperCustomer . T , however, will be Customer . Using GetType() would be much more reliable.

Another useful trick here is dynamic , which is a hidden way of throwing from non-generic to generic. Consider:

 dynamic foo = 123; Bar(foo); void Bar<T>(T bar) { Console.WriteLine(typeof(T)); } 

will write System.Int32 . He flipped over to the correct T "on the fly," despite the fact that he really knew about the object in the compiler ( dynamic is implemented mainly as an object with some fancy bits).

However, to emphasize - I would not use this here: I would simply have:

 public static BusinessObject Clone(this BusinessObject obj) { BusinessObject newObj = (BusinessObject) Activator.CreateInstance(obj.GetType()); var props = newObj.Properties; foreach (var p in props) newObj.Properties[p.Name].SetValue(newObj, obj.Properties[p.Name].GetValue(obj)); return newObj; } 

with dynamic as my backup strategy if I really need generics.

+2
source

Source: https://habr.com/ru/post/1395371/


All Articles