Method resolve() return instance of initialized object from Dictionary, but my question is: is there any way to simplify resolve() method in a way that we still pass type as argument but after we don't need cast it. I thought about generic resolution but for resolve<ClassAbraKadabra>(typeof(ClassAbraKadabra)) looks repetitive and cant simplified.
class Foo {
//something here
}
//reality
class Resolver{
public void proc() {
Foo foo = (Foo) resolve(typeof(Foo));
}
private object resolve(Type type) {
var obj = getInstanceOfObjectFromMapByType(type):
return obj;
}
}
//expected
class Resolver{
public void proc() {
Foo foo = resolve(typeof(Foo));
}
private ??? resolve(Type type) {
//magic here
}
}
//generic way
class Resolver{
public void proc() {
Foo foo = resolve<Foo>(typeof(Foo));
}
private T resolve<T>(Type type) {
var obj = getInstanceOfObjectFromMapByType(type):
return (T)obj;
}
}
Your generic way was almost there, you don't need to pass in the type just do a typeof(T) from inside the generic method.
//generic way
class Resolver{
public void proc() {
Foo foo = resolve<Foo>();
}
private T resolve<T>() {
var obj = getInstanceOfObjectFromMapByType(typeof(T)):
return (T)obj;
}
}
If you really must pass in type then the "reality" way is the only option, you have to do the cast at a higher level and just try to return a common interface that is still useful.
ClassA, ClassB, ClassC and ClassD are all implementing IMyClass interface.
myObj is an instance of one of the classes.
private void setObj<T>()
{
myObj = mycollection.Single(w => w is T);
}
public void Switch()
{
if(myObj is ClassA)
{
setObj<ClassA>();
}
else if(myObj is ClassB)
{
setObj<ClassB>();
}
else if(myObj is ClassC)
{
setObj<ClassC>();
}
else if(myObj is ClassD)
{
setObj<ClassD>();
}
}
How can we refactor the Switch method, so that I have something like this:
public void Switch()
{
// How can we know from `myObj`, which class it is and rewrite
// the whole Switch method like this
// X = `ClassA`, `ClassB`, `ClassC` or `ClassD`
setObj<X>();
}
You cannot pass a generics type parameter as a variable in C#. However, you can get the type via reflection (myObj.GetType()) and pass that as a function parameter from your Switch() function to your setObj() function, which in turn can be compared in your lambda:
private void setObj(Type type)
{
myObj = Objects.Single(o => o.GetType() == type);
}
public void Switch()
{
Type setToThisType = myObj.GetType();
setObj(setToThisType);
}
make Switch a generic method too that accepts an object of type T
public void Switch<T>(T obj) where T : IMyClass
{
setObj<T>();
}
The where T : IMyClass statement ensures that you can only call Switch where obj is an instance of a class implementing IMyClass
void Example()
{
ClassA objA = new ClassA();
Switch(objA); //OK;
ClassX objX = new ClassX();
Switch(objX); //compile-time error since ClassX doesn't implement IMyClass
}
EDIT: after reading the title, I think you would need to have the parameter T obj in the Switch method.
Try using typeof(ClassA)
public void TypeTest(Type t)
{
if(t.Equals(typeof(ClassA))){
}
}
I have 3 classes:
class O
{
}
class A : O
{
}
class B : A
{
}
When I call my code:
List<O> myList = new List<O>();
myList.Add(new A());
myList.Add(new B());
foreach (O obj in myList)
{
if (obj is A)
{
// do something
}
else if (obj is B)
{
//do something
}
}
However I realized that if (obj is A) will be evaluated to be true even when my obj is of class B. Is there a way to write the statement such that it evaluates to true if and only if obj is of class B?
Why don't you define a virtual function in the base class and override it in the derived types, doing what you need in the different cases?
class O {
public virtual void DoSomething() {
// do smtgh in the 'O' case
}
}
class A : O {
public override void DoSomething() {
// do smtgh in the 'A' case
}
}
class B : A {
public override void DoSomething() {
// do smtgh in the 'B' case
}
}
Then your loop becomes
foreach (O obj in myList) {
obj.DoSomething();
}
There are two method GetType and typeof
GetType is a method on object. It provides a Type object, one that
indicates the most derived type of the object instance.
and
Typeof returns Type objects. It is often used as a parameter or as a
variable or field. The typeof operator is part of an expression that
acquires the Type pointer for a class or value type
Try like this
if(obj.GetType() == typeof(A)) // do something
else if(obj.GetType() == typeof(B)) //do something
I'm looking at a function with this pattern:
if( obj is SpecificClass1 )
{
((SpecificClass1)obj).SomeMethod1();
}
else if( obj is SpecificClass2 )
{
((SpecificClass2)obj).SomeMethod2();
}
else if( obj is SpecificClass3 )
{
((SpecificClass3)obj).SomeMethod3();
}
and get a code analysis warning: CA1800 Do not cast unnecessarily.
What's a good code pattern I can use to replace this code with that will be performant and concise.
Update
I didn't say, but obj is declared with type object.
I originally asked two questions here. I've split one off (which nobody had yet answered anyway): Why wouldn't the compiler optimize these two casts into one?
Interface
The best way would be to introduce an interface that all the types implement. This is only possible if the signatures match (or you don't have too many differences).
Using as
If creating an interface is not an option, you can get rid of the CA message by using the following pattern (though this also introduces unnecessary casts and therefore degrades performance a bit):
var specClass1 = obj as SpecificClass1;
var specClass2 = obj as SpecificClass2;
var specClass3 = obj as SpecificClass3;
if(specClass1 != null)
specClass1.SomeMethod1();
else if(specClass2 != null)
specClass2.SomeMethod2();
else if(specClass3 != null)
specClass3.SomeMethod3();
You can also change it to this structure (from my point of view, the above is better in terms of readability):
var specClass1 = obj as SpecificClass1;
if (specClass1 != null)
specClass1.SomeMethod1();
else
{
var specClass2 = obj as SpecificClass2;
if (specClass2 != null)
specClass2.SomeMethod2();
else
{
var specClass3 = obj as SpecificClass3;
if (specClass3 != null)
specClass3.SomeMethod3();
}
}
Registering the types in a dictionary
Also, if you have many types that you want to check for, you can register them in a dictionary and check against the entries of the dictionary:
var methodRegistrations = new Dictionary<Type, Action<object> act>();
methodRegistrations.Add(typeof(SpecificClass1), x => ((SpecificClass1)x).SomeMethod1());
methodRegistrations.Add(typeof(SpecificClass2), x => ((SpecificClass2)x).SomeMethod2());
methodRegistrations.Add(typeof(SpecificClass3), x => ((SpecificClass3)x).SomeMethod3());
var registrationKey = (from x in methodRegistrations.Keys
where x.IsAssignableFrom(obj.GetType()).FirstOrDefault();
if (registrationKey != null)
{
var act = methodRegistrations[registrationKey];
act(obj);
}
Please note that the registrations are easily extendable and that you can also call methods with different arguments in the action.
To avoid the double casting you could do the following
var objClass1= obj as SpecificClass1;
if(objClass1!=null)
objClass1.SomeMethod1();
Regarding the pattern you could make all these classes implement a common interface and make your method receive the interface.
public void SomeMethod(ISpecificInterface specific)
{
specific.SomeMethod1();
}
Can you do something like this here?
interface IBaseInterface
{
void SomeMethod();
}
public class Implementer1:IBaseInterface
{
public void SomeMethod()
{
throw new NotImplementedException();
}
}
public class Implementer2 : IBaseInterface
{
public void SomeMethod()
{
throw new NotImplementedException();
}
}
public class Implementer3 : IBaseInterface
{
public void SomeMethod()
{
throw new NotImplementedException();
}
}
And then, in caller code:
IBaseInterface concrete = GetInstance();
concrete.SomeMethod();
and GetInstance would create class objects based on conditions.
Your classes can be inherite a ISomeMethodInterface like this:
public interface ISomeMethodInterface
{
void SomeMethod();
}
public class SpecificClass1 : ISomeMethodInterface
{
//some code
public void SomeMethod()
{
}
}
public class SpecificClass2 : ISomeMethodInterface
{
//some code
public void SomeMethod()
{
}
}
public class SpecificClass3 : ISomeMethodInterface
{
//some code
public void SomeMethod()
{
}
}
And in your call:
((ISomeMethodsInterface)obj).SomeMethod();
The most extensible solution would probably be inheriting the concrete class while implementing an interface with a SomeMethod implementation that calls the correct SomeMethodx method on the inherited class. That way, you'll keep the existing interface while still keeping the existing methods.
public interface ISomething {
void SomeMethod();
}
public SpecificClass1Wrapper : SpecificClass1, ISomething {
void SomeMethod() { SomeMethod1(); }
}
If the objects are wrapped in this way before they're stored in the object reference, a cast to ISomething and a call to SomeMethod() will replace your entire if/else combination.
If the object on the other hand comes from code you have no way of extending and terse but still clear is what you're going for, you could create a simple helper method;
private bool CallIfType<T>(object obj, Action<T> action) where T : class
{
var concrete = obj as T;
if (concrete == null)
return false;
action(concrete);
return true;
}
You can then write the calls as a simple expression;
var tmp = CallIfType<SpecificClass1>(obj, x => x.SomeMethod1()) ||
CallIfType<SpecificClass2>(obj, x => x.SomeMethod2()) ||
CallIfType<SpecificClass3>(obj, x => x.SomeMethod3());
if(tmp)
Console.WriteLine("One of the methods was called");
Ok, bit rough, but:
public class BaseClass{}
public class SubClass1 : BaseClass
{
public void SomeMethod1()
{
}
}
public class SubClass2 : BaseClass
{
public void SomeMethod2()
{
}
}
public class Class1
{
public Class1()
{
var test = new SubClass1();
var lookup = new Dictionary<Type, Action<object>>
{
{typeof (SubClass1), o => ((SubClass1) o).SomeMethod1() },
{typeof (SubClass2), o => ((SubClass2) o).SomeMethod2() }
};
//probably best to check the type exists in the dictionary first,
//maybe wrap up the execution into a class of it's own so it's abstracted away
lookup[test.GetType()](test);
}
}
How about writing a method
public static class ObjectExtensions
{
public static bool TryCast<T>(this object from, out T to) where T : class
{
to = from as T;
return to != null;
}
}
and using it:
SpecificClass1 sc1;
SpecificClass2 sc2;
SpecificClass3 sc3;
if( obj.TryCast(out sc1) )
{
sc1.SomeMethod1();
}
else if( obj.TryCast(out sc2) )
{
sc2.SomeMethod2();
}
else if( obj.TryCast(out sc3) )
{
sc3.SomeMethod3();
}
Not sure if I'm missing a goal, but here's an option that should work.
if( obj is SpecificClass1 sc1 )
{
sc1.SomeMethod1();
}
else if( obj is SpecificClass2 sc2 )
{
sc2.SomeMethod2();
}
else if( obj is SpecificClass3 sc3 )
{
sc3.SomeMethod3();
}
else
{
throw new exception();
}
You can also
switch (obj)
{
case SpecificClass1 sc1:
sc1.SomeMethod1();
break;
case SpecificClass2 sc1:
sc2.SomeMethod2();
break;
case SpecificClass3 sc1:
sc3.SomeMethod3();
break;
default:
throw new Exception();
}
i'm trying to do fancy stuff like this:
i have following code:
public interface IMyInterface
{
void Method1();
}
public interface IClassFactory
{
object GetObject();
}
public interface IGenericClassFactory<T> where T: IMyInterface
{
T GetObject();
}
public class MyClass : IMyInterface
{
public void Method1()
{
Console.WriteLine("Medota 1");
}
}
public class MyFactory : IClassFactory
{
public object GetObject()
{
return new MyClass();
}
}
public class MyGenericFactory<T> : IGenericClassFactory<T> where T : IMyInterface, new()
{
public T GetObject()
{
// T t = new T();
//return t;
//var ctor = typeof(T).GetConstructor(new Type[0]);//1] { typeof(int) });
//if (ctor != null)
//{
// return (T)ctor.Invoke(new object[0]); // new object[1] { 5});
// //return Activator.CreateInstance<T>(); //to samo co wyzej tylko nie jest bezpieczne
//}
//throw new InvalidOperationException("T nie posiada domyślnego konstruktora");
// return Activator.CreateInstance<T>(); //bez parametrów
// return (T)Activator.CreateInstance(typeof(T), 5, "EOG", new object()); // z parametrami
return new T();
}
}
static void Main(string[] args)
{
IClassFactory factory;
factory = new MyFactory();
IGenericClassFactory<IMyInterface> genFactory;
genFactory = new MyGenericFactory<MyClass>(); //Do not compile!
MyClass obj = genFactory.GetObject() as MyClass;
obj.Method1();
Console.ReadKey();
}
I can do this like:
IGenericClassFactory<IMyInterface> genFactory;
genFactory = new MyGenericFactory<MyClass>();
//so i can chose object to create
but i think it is pointless because i want to have Factory of more then one object.
Can u help me?
Thx in advance
You should not make your factory class generic but the method GetObject should be generic:
public T GetObject<T>() where T: IMyInterface, new()
Then:
static void Main(string[] args)
{
var factory = new MyFactory();
var obj = factory.GetObject<MyClass>();
obj.Method1();
Console.ReadKey();
}
So all in all you should get rid of your generic code and simply modify your MyFactory class
public class MyFactory : IClassFactory
{
public T GetObject<T>()
{
//TODO - get object of T type and return it
return new T();
}
}
By the way - I am not sure what is the purpose of having this generic implementation? Does it make any sense from the perspective of the usage of Factory pattern?