I'm trying to optimize a method and can't get to the solution..
I have the following class:
public class X : MyInterface<Model>
{
public void Execute(Model m) { }
}
I am trying to invoke Execute(...)
I know the Type of X and I know the Type of Model.
This works:
(here logic to find the correct method).Method.Invoke(InstanceX, new object[] { m });
This does not but should work faster:
(here logic to find the correct method).Method.CreateDelegate(Expression.GetDelegateType(typeof(m)), instanceX);
Error:
Cannot bind to the target method because its signature or security transparency is not compatible with that of the delegate type.
Again; trying to optimize, so any other solution that works faster than the reflection Invoke would be cool.
Solution without reflection (to create delegate):
// assuming existence of class BaseModel and class XModel : BaseModel
public interface IBaseClass {
void Execute(BaseModel model);
}
public abstract class BaseClass<TModel> : IBaseClass where TModel : BaseModel {
public void Execute(BaseModel model) {
this.Execute((TModel)model);
}
protected abstract void Execute(TModel model);
}
public class X : BaseClass<XModel> {
protected override Execute(XModel model) {
...
}
}
Sample usage:
var typeX = typeof(X);
var typeXModel = typeof(XModel);
var x = (IBaseClass)Activator.CreateInstance(typeX);
x.Execute((BaseModel)Activator.CreateInstance(typeXModel));
Related
I am trying to implement generic solution using Activator.CreateInstace()
Below I have interface,
public interface INewReleaseValidationRule<T> where T : INewReleaseValidationEntity
{
void Run(CtxNewRelease ctx, IEnumerable<T> entities);
string GetMessage(string messageName, string fallbackMessage);
}
public interface INewReleaseValidationEntity
{}
My class CustomerAssociation is:
public class CustomerAssociation : INewReleaseValidationEntity
{
public void Run(Context.Ctx context, IList<INewReleaseValidationEntity> entitiesObject)
{}
}
Then I have view model which is also implementing INewReleaseValidationEntity.
public class ForecastViewModel : INewReleaseValidationEntity
{
}
Then,
public partial class ValidationRule
{
public void Run(Ctx context, List<ForecastViewModel > entity)
{
var validation = this.GetExecutionType();
var execution = (INewReleaseValidationRule<entity>)Activator.CreateInstance(validation);
execution.Run(context, entity.ToArray());
}
}
In above highlighted statement I am getting error.
If I use,
var execution = (CustomerAssociation)Activator.CreateInstance(validation);
then it works perfectly fine. But I want to provide the explicit type (in this case CustomerAssociation) dynamically.
All my explicit type (that is CustomerAssociation) and others will be inherited from INewReleaseValidationRule<T>.
If I write
var execution = (INewReleaseValidationRule<ForecastViewModel>)Activator.CreateInstance(validation);
then getting runtime error,
Unable to cast object of type 'CustomerAssociation' to type 'INewReleaseValidationRule`1[ForecastEstimateViewModel]'.
It's a bit unclear from the code what the actual intent is, but you can try adjusting your validator's run method to take a generic type like this:
public partial class ValidationRule
{
public void Run<T>(Ctx context, List<ForecastViewModel> entity)
where T : class, INewReleaseValidationEntity
{
var execution = (T)Activator.CreateInstance<T>();
execution.Run(context, entity.ToArray());
}
}
And call it like this:
new ValidationRule().Run<CustomerAssociation(context, entities);
Suppose I have a base class like the following
public abstract class BaseHelloWorld<T> where T : BaseEntity
{
public abstract IEnumerable<T> DoSomething();
}
and another like
public class BaseEntity
{
public abstract void DoSomethingInPayload();
}
Then I have 4 classes like:
public class Payload1 : BaseEntity
{
public override void DoSomethingInPayload()
{
Console.Write("Hello world");
}
}
public class Class1 : BaseHelloWorld<Payload1>
{
public override IEnumerable<Payload1> DoSomething()
{
return new List<Payload1> { };
}
}
public class Payload2 : BaseEntity
{
public override void DoSomethingInPayload()
{
Console.Write("Goodbye world");
}
}
public class Class2 : BaseHelloWorld<Payload2>
{
public override IEnumerable<Payload2> DoSomething()
{
return new List<Payload2>() { };
}
}
Although I have shown code here, suppose these where third party libraries that I don't have code for and I want to extend them. What I want to do is to be able to create a single extension method that will allow me to call the DoSomethingInPayload() method on the payload class similar to
public static void CallDoSomething<T>(this BaseHelloWorld<T> theClass) where T: BaseEntity
{
theClass.DoSomethingInPayload();
}
Obviously this will not work so I started looking at expression trees. My reading suggests this is possible to do with expression trees but I cant figure it out. After hours of trying and getting nowhere I am unsure if my theory is correct. Therefore could you please tell me:
A) Is it possible to do this with expression trees
B) If so how would I do it?
Thanks in advance
Your own example is not working because T is a different type in the input and return parameters.
Indeed, as #AleksAdreev mentioned, you could simply try:
public static IEnumerable<T> CallDoSomething<T>(this BaseHelloWorld<T> theClass)
{
return theClass.DoSomething();
}
Which can then be called as follows:
var someClass = new Class2();
var someResult = someClass.CallDoSomething();
I want to create methods that only will able to use if the generic type of a class is from a specific type.
For example, I have two abstract classes NamedEntity and KeyedEntity and I have a class which works with a generic type: MyClass<T>
I would like to create a method X on MyClass<T> which only will be able if the T is a NamedEntity and a method Y on MyClass<T> which only will be able if T is a KeyedEntity. If T is both, both methods will be shown.
I don't want to implement the method independently of the generic type and thrown an error if the type is not the correct type to use the method, but if this is the only way I will do.
If I could inherit from multiple classes it would be easy, but how C#only allow me to inherit from one class it is being hard to think about for me.
EDIT
I agree with all your points. I will try to explain better:
I have an abstract service class, which could work with all the database entities of my system.
All entities could have the "default" methods like "GetById(long id); Create(T entity); Update(T entity)" and it's possible because I am working with an ORM (Nhibernate).
I would like to create the method "GetByName" but not all of the entities have the property "Name", so it will be better if the method GetByName appears only for services which works with a Generic Type that force the entity to have the property "Name", this Generic Type should be the entity class, if I use interfaces (INamedEntity, IKeyedEntity) the problem continue being the same.
If I'm understanding you correctly, you are trying to achieve something like the following (non compilable code follows):
class MyClass<T>
{
public void X(T t) where T: NamedEntity { ... }
public void X(T t) where T: KeyedEntitiy { ... }
}
This won't compile You can not constrain T at method level, only at class level.
Ok. Constraining at top level seems useless, because you'd need to constrain to both NamedEntity and KeyedEntity which is self defeating, so let's constrain at method level:
class MyClass<T>
{
public void X<Q>(Q q) where Q: NamedEntity { ... }
public void X<Q>(Q q) where Q: KeyedEntitiy { ... }
}
Now this won't compile because constraints on generic type parameters are not part of a method's signature. The two methods X would essentially be the same overload and therefore the compiler will flag the second method with an error; method X already exists....
Also, you'd need to check that Q and T are actually compatible and this will only be possible at runtime, not at compile time...yuck!
Ok, then the only option seems to be overloading:
public X(NamedEntity entity) { ... }
public X(KeyedEntity entity) { ... }
Of course this is also far from safe at compile time; you still need to check that the right method is called for the actual type of T and this check can only be done at runtime. Yuck again...
Also, what happens if you have the following:
class Foo: NamedEntity, KeyedEntity { }
myClass.X(new foo()); //now what? What X is called?
This whole setup just seems completely off, you should rethink you approach or give more information on what exactly is it you are trying to achieve.
UPDATE Ok, all clearer now. The methods dont share the same name, thats a big difference!
Based on new info in your question, I would recommend the following approach:
public interface IKeyedIdentity
{
long Id { get; }
}
public interface INamedIdentity: IKeyedIdentity
{
string Name { get; }
}
public class MyClass<T> where T: IKeyedIdentity
{
public void Create(T entity) { ... }
public void Update(T entity) { ... }
public T GetById(long id) { ... }
public Q GetByName<Q>(string name)
where Q : T, INamedEntity
{ ... }
}
Here it makes sense to make the method generic itself because there is a relationship between T and Q you can leverage. This wasn't altogether clear before.
Downside, you have to explicitly supply Q in calls to GetName, I can't think of any compile time safe set up that would avoid this.
UPDATE #2: I think you have to take a step back and implement specialized MyClass<T>s that know how to deal with each expected entity type.
Consider the following code, it should give you enough ideas to implement a similar pattern in your particular scenario:
public static class EntityManagerProvider
{
public static EntityManager<Q> GetManager<Q>()
{
if (typeof(INamedIdentity).IsAssignableFrom(typeof(Q)))
return typeof(NamedEntityManager<>).MakeGenericType(typeof(Q)).GetConstructor(new Type[] { }).Invoke(new Type[] { }) as MyClass<Q>;
if (typeof(IKeyedIdentity).IsAssignableFrom(typeof(Q)))
return typeof(KeyedEntityManager<>).MakeGenericType(typeof(Q)).GetConstructor(new Type[] { }).Invoke(new Type[] { }) as MyClass<Q>;
return null;
}
public abstract class EntityManager<T>
{
public void Create(T entity) { ... }
public void Update(T entity) { ... }
public abstract T GetById(long id);
public abstract T GetByName(string name);
}
private class KeyedEntityManager<Q> : EntityManager<Q> where Q : IKeyedIdentity
{
public override Q GetById(long id) { return default(Q); }
public override Q GetByName(string name) { throw new NotSupportedException(); }
}
private class NamedEntityManager<Q> : EntityManager<Q> where Q : INamedIdentity
{
public override Q GetById(long id) { throw new NotSupportedException(); }
public override Q GetByName(string name) { return default(Q); }
}
}
Now you can do the following:
var myNamedFooManager = MyClassProvider.GetMyClass<NamedFoo>();
var namedFoo = myNamedFooManager.GetByName("Foo"); //I know this call is safe.
var myKeyedFooManager = MyClassProvider.GetMyClass<KeyedFoo>();
var keyedFoo = myNamedFooManager.GetById(0); //I know this call is safe.
Downside: if you need to interact with a given entity that is both keyed and named in either way, you'll have to use two distinct managers.
I have the following classes:
public interface IService
{
void ApplyChanges<T>(T parameters) where T : ParamBase;
}
public class ServiceBase : IService
{
public virtual void ApplyChanges<T>(T parameters) where T : ParamBase
{ }
}
public abstract class Service : ServiceBase
{
public override void ApplyChanges<T>(T parameters) where T : ParamBase
{
Console.WriteLine(parameters.Param2);
//Apply changes logic here...
}
}
public abstract class ParamBase
{
public string Param1 { get; set; }
}
public class ParamA : ParamBase
{
public string Param2 { get; set; }
}
Here my test main class:
void Main()
{
var service = new Service();
var paramA = new ParamA();
paramA.Param2 = "Test2";
service.ApplyChanges<ParamA>(paramA);
}
What is wrong with that implementation? How can I access parameters.Param2from the overriden ApplyChanges method in my Service class?
The general idea is that I have a ServiceBase and I want to be able for its derived classes to pass different parameter types to the ApplyChanges method.
I'm making a leap here, but it sounds like you intend to have multiple "services", each with an associated parameter type.
Putting a type parameter on the method, as you have done in the example, forces all implementations of that method to be polymorphic. (The technical term for this is higher-rank quantification.)
Instead, you should associate the type parameter with the service itself. This allows a given implementation of the contract to declare which parameter type it's associated with. While you're at it, I wouldn't bother with the base classes or the type bounds.
interface IService<in T>
{
void ApplyChanges(T param);
}
class Param1
{
public int X { get; set; }
}
class Service1 : IService<Param1>
{
public void ApplyChanges(Param1 param)
{
param.X = 123;
}
}
class Param2
{
public int Y { get; set; }
}
class Service2 : IService<Param2>
{
public void ApplyChanges(Param2 param)
{
param.Y = 456;
}
}
You shouldnt impose stronger constraints for method overrides. An overridden method should expand the possible input parameters and reduce the possible outcomes. Otherwise it breaks Liskov Substitution Principle. C# does not allow you to do that.
That said, if you really want it, you could. You won't get compiler warnings in the calling code though. Use that solution if you cannot change the base class.
public class Service<TParam> : Service where TParam : ParamA
{
public override void ApplyChanges<T>(T parameters)
{
Console.WriteLine((parameters as TParam).Param2);
}
}
A better solution would be to add a type parameter to ServiceBase and IService.
public interface IService<TParam>
where TParam : ParamBase
{
void ApplyChanges(TParam parameters);
}
public abstract class ServiceBase<TParam> : IService<TParam>
where TParam : ParamBase
{
public virtual void ApplyChanges(TParam parameters)
{ }
}
public class Service : ServiceBase<ParamA>
{
public override void ApplyChanges(ParamA parameters)
{
Console.WriteLine(parameters.Param2);
}
}
Really, instead of replacing the interface's generic type, it is cleaner to use a "Type Guard". I say cleaner because the interface's method signature stays consistent, and really, what's more important than how your interface is used? (Obviously puppies are more important)
Within the method itself, you can make sure that the type is the one desired as such...
public void Method(ParentRequest req){
if(req is ChildRequest request){
//Do logic here
} else {
throw new Exception($"request is of type {req.GetType().Name} and must be of type ParentRequest");
}
}
I have two parallel class hierarchy, where the first hierarchy is for an API while the second is used in the model layer.
The same type has one representation(class) in each hierarchy and I want to 'bind' (more later) this two classes in order to use generics.
API
/ \
ApiA ApiB
Model
/ \
ModelA ModelB
For instance, once this function
public string DoSomething<APIType> (APIType value) {
gets an APIType as argument (e.g. ApiB), I want to call the associated generic method that takes a ModelType as type argument (ModelB in this case).
I tried something similar to this:
public string DoSomething (ApiType value) where ModelType: Model where ApiType : API
But I then discover that C# can't do partial inference, so this:
class ApiB : Api<ModelB> {}
ApiB obj;
DoSomething(obj)
can't work (both type arguments are required)
I tried to implement something similar to C++ traits but it did not work.
It would be possible to use only Type, but I am doing this in order to get the additional compiler checking.
I guess this is not a big problem, however I would like to know if someone knows a solution.
It's very complex question. Check this code, I've replaced associated generic method call with generic constructor of List. Coment if there is difference between what you questioned and what I understood from question.
class Program
{
public class Model { }
public class ModelB : Model { }
public class Api<T> where T : Model
{
public List<T> CallGenericMethod()
{
return new List<T>();
}
}
public class ApiB: Api<ModelB> { }
public static string DoSomething<T>(Api<T> a) where T : Model
{
var b = a.CallGenericMethod();
return b.GetType().ToString();
}
static void Main(string[] args)
{
ApiB a = new ApiB();
Console.WriteLine(DoSomething(a));
}
}
Edit two types generic version
public class Api<TApi, TModel> where TApi: Api<TApi, TModel> where TModel : Model
{
public List<TModel> CallGenericMethod()
{
return new List<TModel>();
}
}
public class ApiB: Api<ApiB, ModelB> { }
public static string DoSomething<TApi, TModel>(Api<TApi, TModel> a) where TApi : Api<TApi, TModel> where TModel: Model
{
return new Dictionary<TApi, TModel>().GetType().ToString();
}