I have a Reflection method, which I load an Instance of an class with a specific name. I have an abstract class which define my classes. Now I also have an interface in the constructor of this abstract class. It's a bit hard to explain and I'm not sure if it's a correct way to implement my problem. But here is my source code, which should explain the most:
Program:
private static void Main(string[] args)
{
int result;
if (args.Length > 0)
{
string jobName = args[0];
Type[] types = Assembly.GetAssembly(typeof(Task)).GetTypes();
foreach (Type type in types)
{
if (type.Name == jobName)
{
//Here is my problem. I need my Interface instead of null
_job = (Task)Activator.CreateInstance(type, null);
}
}
if (_job != null)
{
result = _job.Run(args);
}
}
//Dispose the Job
_job = null;
}
Task:
public abstract class Task
{
public IArgument Argument;
protected Task(IArgument argument)
{
Argument = argument;
}
public int Run(string[] args)
{
int result;
if (SetArguments(args))
{
result = Work();
}
return result;
}
protected abstract int Work();
Interface:
public interface IArgument
{
bool SetArguments(string[] args);
}
Now I can create an "Task" class and an "Argument" class:
public class ImportArgument : IArgument
{
public bool SetArguments(string[] args)
{
return true;
}
}
public class ImportTask : Task
{
protected override int Work()
{
return 1;
}
public ImportTask(IArgument argument) : base(argument)
{
Argument = new ArticleImportArgument();
}
}
What do you guys think. Is there a way where I can create an Instance of the task class with an Interface in the constructor? Is there another way to solve this problem? I could also create an abstract method in my Task class where I have to implement my Interface, but I think the constructor would be a better way.
Related
Can I use raw type in C# like Java or is there a workaround for this? I know using Raw Type in Java is bad practice but that can solve my current problem.
I have an object that has a field holding a Pool, so that it can return to that Pool whenever it's done with its job.
//C#
public class MyObject : IPoolable
{
public Pool<MyObject> pool;
}
But if there is a new kind of object (ex: MovableObject), I want my pool field has Pool<MovableObject> not Pool<MyObject>. (There are also many kinds of objects derived from MovableObject or MyObject).
In Java, I could define pool field a raw type of Pool so that there is no compiling error.
//Java
public class MyObject implements IPoolable
{
public Pool pool;
}
I'm using a method to return all kinds sof objects in both versions. In Java, it works well but in C#, it has compiling error.
//Java
static public <T extends MyObject> T createObject(Class<T> type) {
Pool<T> pool = Pools.get(type);
T obj= pool.obtain();
obj.setPool(pool); //This won't have any problem since it is raw type
return obj;
}
//C#
public static T CreateObject<T>() where T : MyObject
{
Pool<T> pool = Pools.GetPool<T>();
T obj= pool.Obtain();
obj.Pool = pool; //Error: cannot convert Pool<T> to Pool<MyAction>
return obj;
}
Edit 1: Providing other classes and Minimal, Reproducible Example
public interface IPoolable
{
void Reset();
}
public abstract class Pool<T> where T : IPoolable
{
private readonly Stack<T> freeObjects = new Stack<T>();
public Pool() { }
protected abstract T InstantiateObject(object[] args);
public T Obtain(object[] args = null)
{
return freeObjects.Count == 0 ? InstantiateObject(args) : freeObjects.Pop();
}
public void Free(T obj)
{
if (obj != null)
{
freeObjects.Push(obj);
Reset(obj);
}
}
protected virtual void Reset(T obj)
{
obj.Reset();
}
public void Clear()
{
freeObjects.Clear();
}
}
//ReflectionPool
public class ReflectionPool<T> : Pool<T> where T : IPoolable
{
public ReflectionPool() : base()
{
}
protected override T InstantiateObject(object[] args)
{
return (T)Activator.CreateInstance(typeof(T), args);
}
}
public class Pools
{
static private readonly Dictionary<Type, object> typePools = new Dictionary<Type, object>();
static public Pool<T> GetPool<T>(int max) where T : IPoolable
{
Type type = typeof(T);
if (!typePools.TryGetValue(type, out object pool))
{
pool = new ReflectionPool<T>();
typePools.Add(type, pool);
}
return (Pool<T>)pool;
}
static public Pool<T> GetPool<T>() where T : IPoolable
{
return GetPool<T>(100);
}
}
So in MyObject class, there is a method making my object doing something, after completing it, the current object need to be returned to Pool
//Base Object
public abstract class MyObject : IPoolable
{
public Pool<MyObject> pool; //This is still a problem
public void CallMe()
{
if (Act()) //If this object completing acting
{
ToPool();
}
}
public abstract bool Act();
public void ToPool()
{
pool.Free(this);
pool = null;
}
public abstract void Reset();
}
//Movable Object
public class MovableObject : MyObject
{
//public Pool<MyObject> pool; //Put this here as comment because I want it become Pool<MovableObject>
public override bool Act()
{
return true; //Return false if not reach destination
}
public override void Reset() { }
public override string ToString()
{
return "Movable";
}
}
//I'm using this class for create object I want
public class ObjectFactory
{
public static T CreateObject<T>() where T : MyObject
{
Pool<T> pool = Pools.GetPool<T>();
if(pool != null)
{
T obj = pool.Obtain();
obj.pool = pool; //Error here: Cannot implicitly convert type 'Pool<T>' to 'Pool<MyObject>'
return obj;
}
return null;
}
public static MovableObject MovableObject()
{
return CreateObject<MovableObject>();
}
}
Edit 2: Re-Updated code in edit 1
//Program.cs
public interface TestVal
{
//Input Param
string Input { get; }
//will return output
TestValRes ValidateRe(string input);
}
class MyClass : ITestVal
{
static void Main(string[] args)
{
var instance = new MyClass();
instance.Run();
}
public void Run()
{
ValidateRe("test");
}
public ITestValRes ValidateRe(string input)
{
return null; // return an instance of a class implementing ITestValRes here.
}
}
//TestvalRes.cs
public interface TestvalRes
{
string Input { get; }
bool IsValid { get; }
}
So I just want to pass a string to the TestVal, do validation and call TestvalRes to return whether it is Valid or not, and if Invalid, why? So the validation will be done in the first public interface - TestVal, however I still need to call it inside the Main(), right?
First off, I'd recommend following C# naming conventions and name your interfaces ITestVal and ITestValRes respectively.
Next, static method cannot call instance methods in the same class (without creating an instance and using that). You need to create an instance of the class and pass control of the application flow to that:
class MyClass : ITestVal
{
static void Main(string[] args)
{
var instance = new MyClass();
instance.Run();
}
public void Run()
{
ValidateRe("test");
}
public ITestValRes ValidateRe(string input)
{
return null; // return an instance of a class implementing ITestValRes here.
}
}
I'm looking for RealProxy replacement in .NET Core, and this issue forwards me to DispatchProxy.
It has simple API, but it's unclear, how to wrap existing object into proxy.
E.g., having this interface:
interface IFoo
{
string Bar(int boo);
}
and this implementation:
class FooImpl : IFoo
{
public string Bar(int boo)
{
return $"Value {boo} was passed";
}
}
how to get what I want?
class Program
{
static void Main(string[] args)
{
var fooInstance = new FooImpl();
var proxy = DispatchProxy.Create<IFoo, FooProxy>();
var s = proxy.Bar(123);
Console.WriteLine(s);
}
}
class FooProxy : DispatchProxy
{
protected override object Invoke(MethodInfo targetMethod, object[] args)
{
return targetMethod.Invoke(/* I need fooInstance here */, args);
}
}
Since DispatchProxy descendants must have parameterless constructor, the only idea I have is to invent some method, like this:
class FooProxy : DispatchProxy
{
private object target;
public void SetTarget(object target)
{
this.target = target;
}
protected override object Invoke(MethodInfo targetMethod, object[] args)
{
return targetMethod.Invoke(target, args);
}
}
and use it this way:
var fooInstance = new FooImpl();
var proxy = DispatchProxy.Create<IFoo, FooProxy>();
((FooProxy)proxy).SetTarget(fooInstance);
// the rest of code...
Is this correct approach?
You are right that there is no other option here than to cast the generated IFoo to the known proxy type (FooProxy) and use a custom method or property on FooProxy. There is no public API to add constructor arguments or return the proxy as the implementation type. However, DispatchProxy.Create() will return an instance of a subclass of FooProxy whose type is generated at runtime via reflection and IL emitting.
If you are looking at other ways to quickly wrap an implementation and replace interface methods / virtual methods, I suggest using mocking frameworks instead (FakeItEasy, Moq, NSubstitute etc.).
You need to create your own Generic class that inherit from DispatchProxy and has own static Create that has an extra parameter from type target.
example
public class AopAction<T>:DispatchProxy
{
#region Private Fields
private Action<MethodInfo,object[],object> ActAfter;
private Action<MethodInfo,object[]> ActBefore;
private Action<MethodInfo,object[],Exception> ActException;
private T Decorated;
#endregion Private Fields
#region Public Methods
public static T Create(T decorated,Action<MethodInfo,object[]> actBefore = null,Action<MethodInfo,object[],object> actAfter = null,Action<MethodInfo,object[],Exception> actException = null)
{
object proxy = Create<T,AopAction<T>>();
SetParameters();
return (T)proxy;
void SetParameters()
{
var me = ((AopAction<T>)proxy);
me.Decorated = decorated == null ? throw new ArgumentNullException(nameof(decorated)) : decorated;
me.ActBefore = actBefore;
me.ActAfter = actAfter;
me.ActException = actException;
}
}
#endregion Public Methods
#region Protected Methods
protected override object Invoke(MethodInfo targetMethod,object[] args)
{
_ = targetMethod ?? throw new ArgumentException(nameof(targetMethod));
try
{
ActBefore?.Invoke(targetMethod,args);
var result = targetMethod.Invoke(Decorated,args);
ActAfter?.Invoke(targetMethod,args,result);
return result;
}
catch(Exception ex)
{
ActException?.Invoke(targetMethod,args,ex);
throw ex.InnerException;
}
}
#endregion Protected Methods
}
to use your example
var proxy=AopAction<IFoo>.Create(new FooImpl());
I'm working on a framework right now and the motto is "no redundancy" and "I don't want to know the vendor specifics" so most things are handled through Interfaces and Generic classes. Now I had the situation where I have an abstract class that wants to match things depending on it's own Enum variable se but it shouldn't have to know how the vendor provides a relatable variable to be matched to se. The vendor could have decided an integer, an Enum or a string would be the best to save that information but honestly I don't want to know.
So I thought well no problem have an abstract static method that must be provided by every implementation of a wrapper to compare se with the vendor specific way of saving that information.
//The original version I wanted to be possible
public abstract class AbstractGenericClass<TWrapper<T>, T> where TWrapper : AbstractGenericWrapper<T> {
protected TWrapper tWrapper;
//our SomeEnum se is somehow relatable to every T
//but we don't want to know how
protected SomeEnum se = ...;
//called on Start
public void Start() {
List<T> ts = FindObjectsOfType<T>;
foreach (T t in ts) {
if(T.Compare(t, this.se)) {
tWrapper = new TWrapper(t);
}
}
}
}
public abstract class AbstractGenericWrapper<T> {
T _t;
public AbstractGenericWrapper(T t) {
_t = t;
}
public static abstract bool Compare(T t, SomeEnum someEnum);
}
public class ConcreteNongenericWrapper : AbstractGenericWrapper<VendorSpecificImplementation> {
public static bool Compare(VendorSpecificImplementation t, SomeEnum someEnum) {
return t.vendorVariable.toLower().Equals(Enum.GetValues(typeof(someEnum), someEnum));
}
}
public class OtherConcreteNongenericWrapper : AbstractGenericWrapper<OtherVendorSpecificImplementation> {
public static bool Compare(OtherVendorSpecificImplementation t, SomeEnum someEnum) {
return t.otherVendorVariable % 3 == (int) someEnum;
}
}
public class SomeImplementation {
public static void main() {
AbstractGenericClass<ConcreteNongenericWrapper<ConcreteNongeneric>, ConcreteNongeneric> foo
= new AbstractGenericClass<ConcreteNongenericWrapper<ConcreteNongeneric>, ConcreteNongeneric>();
AbstractGenericClass<OtherConcreteNongenericWrapper<OtherConcreteNongeneric>, OtherConcreteNongeneric> bar
= new AbstractGenericClass<OtherConcreteNongenericWrapper<OtherConcreteNongeneric>, OtherConcreteNongeneric>();
foo.Start();
bar.Start();
}
}
I found out that that isn't possible and I wanted to know if this version down below is the best/only way of doing it? It has redundancy and I don't like it and it is longer.
//An attempt at a solution:
public abstract class AbstractGenericClass<TWrapper<T>, T> where TWrapper : AbstractGenericWrapper<T> {
protected TWrapper tWrapper;
//our SomeEnum se is somehow relatable to every T
//but we don't want to know how
protected SomeEnum se = ...;
//called on start
public abstract void Start();
}
public abstract class AbstractGenericWrapper<T> {
T _t;
public AbstractGenericWrapper(T t) {
_t = t;
}
}
public class ConcreteNongenericClass : AbstractGenericClass<VendorSpecificImplementation> {
//called on start
public override void Start() {
List<VendorSpecificImplementation> ts = FindObjectsOfType<VendorSpecificImplementation>;
foreach (VendorSpecificImplementation t in ts) {
if(t.vendorVariable.toLower().Equals(Enum.GetValues(typeof(someEnum), someEnum))) {
tWrapper = new ConcreteNongenericWrapper(t);
}
}
}
}
public class ConcreteNongenericWrapper : AbstractGenericWrapper<VendorSpecificImplementation> {
}
public class OtherConcreteNongenericClass : AbstractGenericClass<OtherVendorSpecificImplementation> {
//called on start
public void Start() {
List<OtherVendorSpecificImplementation> ts = FindObjectsOfType<OtherVendorSpecificImplementation>;
foreach (OtherVendorSpecificImplementation t in ts) {
if(t.otherVendorVariable % 3 == (int) someEnum) {
tWrapper = new OtherConcreteNongenericWrapper(t);
}
}
}
}
public class OtherConcreteNongenericWrapper : AbstractGenericWrapper<OtherVendorSpecificImplementation> {
}
public class SomeImplementation {
public static void main() {
AbstractGenericClass<ConcreteNongenericWrapper<ConcreteNongeneric>, ConcreteNongeneric> foo
= new AbstractGenericClass<ConcreteNongenericWrapper<ConcreteNongeneric>, ConcreteNongeneric>();
AbstractGenericClass<OtherConcreteNongenericWrapper<OtherConcreteNongeneric>, OtherConcreteNongeneric> bar
= new AbstractGenericClass<OtherConcreteNongenericWrapper<OtherConcreteNongeneric>, OtherConcreteNongeneric>();
foo.Start();
bar.Start();
}
}
Thank you very much for your time and help!
I'm totally new to C# generic so I have the following problem. I have 2 classes. One instance based and another generic class.
I want to have a property in the 1st class of the type of 2nd generic class.
something on these lines....functionality wise.
public class SampleClass
{
private SampleGenericClass<T> sampleClass;
public SampleClass(string name, int age, string version)
{
if(version == "1.0")
{
this.sampleClass = new SampleGenericClass<int>(name, age);
}
else
{
this.sampleClass = new SampleGenericClass<long>(name.age);
}
}
public void Load()
{
this.sampleClass.Load();
}
public void Open()
{
this.sampleClass.Open();
}
public void Close()
{
this.sampleClass.Close();
}
}
My 2nd generic class is something like this
internal class SampleGenericClass<T> where T : class
{
private string name;
private string age;
public SampleGenericClass(string name, int age)
{
this.name = name;
this.age = age;
}
public void Load()
{
// Do something based on type
if(typeof(T) == typeof(int))
{
// load int type
}
else if(typeof(T) == typeof (long))
{
// load long type
}
else
{
throw new ArgumentException("Un supported type");
}
}
public void Open()
{
// Do something based on type
if(typeof(T) == typeof(int))
{
// open int type
}
else if(typeof(T) == typeof (long))
{
// open long type
}
else
{
throw new ArgumentException("Un supported type");
}
}
public void Close()
{
// Do something based on type
if(typeof(T) == typeof(int))
{
// close int type
}
else if(typeof(T) == typeof (long))
{
// close long type
}
else
{
throw new ArgumentException("Un supported type");
}
}
}
Now I understand that CLR doesnt support generic properties or constructors.
So how can I solve this problem? I still want to have a generic class and somehow instantiate it in my 2nd class based on the params passed to constructor of 1st class, so as to call the methods load,openm, close in the 2nd class .
Thanks for your help.
NOTE: I know the above code doesn't compile, bcoz CLR doesnt support generic properties and constructors. It's just for illustrative purpose of what I want to achieve conceptually
IMO you should decide in upper level, what is the type of SampleClass In fact you should define it as generic:
public class SampleClass<T> where T : ....
{
private SampleGenericClass<T> sampleClass;
public SampleClass(string name, int age, string version)
{
this.sampleClass = new SampleGenericClass<T>(name, age);
}
public void Load()
{
this.sampleClass.Load();
}
}
and create your SampleClass base on version in upper levels(and related generic).
e.g:
Main method:
if (version == "1")
{
DoAction<int>();
}
else
DoAction<long>();
.....
void DoAction<T>()
{
SampleClass<T> s = new SampleClass<T>(...)
}
Also as I can see you don't need T type for your member variables, so you can move it to lower level in function calls.
Either declare a concrete type
public class SampleClass {
private SampleGenericClass<int> sampleClass;
...
}
or add a generic type parameter to SampleClass
public class SampleClass<T> where T : class {
private SampleGenericClass<T> sampleClass;
...
}
Interface:
public interface ISampleGenericClass
{
void Load();
void Open();
void Close();
}
The generic class implements this:
internal class SampleGenericClass<T> : ISampleGenericClass
{
...
}
And SampleClass
public class SampleClass
{
private ISampleGenericClass sampleClass;
....
}
I removed the class constraint, because int and long are value types, so they can't be used in the current form.