Find a class that it has a specific property value - c#

Consider I have these classes
class BaseClass
{
public int Variable {get; set;}
}
class Class1:BaseClass
{
public Class1()
{
Variable=1;
}
}
class Class2:BaseClass
{
public Class2()
{
Variable=2;
}
}
In another place I want to do this:
public BaseClass MyMethod(int i)
{
//I want if i is 1 this method returns Class1
//And if i is 2 this method returns Class2.
}
A solution is using switch statement. But my namespace has a lot of class and using switch results a lot of code lines.

Your comment "But my namespace has a lot of class and using switch results a lot of code lines." tells me that you are doing something wrong.
This is classic problem, easily solved by factory pattern, using switch would be the best solution here:
switch(num) {
case 1: return new Class1();
case 2: return new Class2();
default: throw new ArgumentException();
}
Maybe you should split your namespace?
Other solution with is a bit ugly because you will lose compile time checking, is to use Activator:
return (BaseClass)Activator.CreateInstance("AssemblyName", "Class" + num)
Based on comment, 100 classes and must select one.
public static class AmazingFactory {
private static IDictionary<int, Type> _num2Type;
private static void InitializeFactory() {
var type = typeof(BaseClass);
// get all subclasses of BaseClass
var types = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(s => s.GetTypes())
.Where(p => type.IsAssignableFrom(p));
foreach(var type in types) {
int numberAtTheEnd = int.Parse(Regex.Match(type.Name, #"\d+$").Value);
_num2Type[numberAtTheEnd] = type;
}
}
public static BaseClass Create(int num) {
if (_num2Type == null)
InitializeFactory();
return (BaseClass)Activator.CreateInstance(_num2Type[num]);
}
}

Looks like you don't want to return a class, but rather an instance of a class. The next question is where do you want to get your object from? If they are stored in some collection like
items = new List<BaseClass>();
items.add(new Class1());
items.add(new Class2());
then you can write something like
public BaseClass MyMethod(int i)
{
return items.First(item=>item.Variable == i);
}
If you want to create a new instance with each call to MyMethod than you'll have to use switch\if (or use Reflection, but that's not a recommended approach)

Related

C# Generics Specialization

I created a specialization for a generic like code below:
public class BaseGeneric<T>
{
public static T DoStuff()
=> default;
}
public class SpecializedFromBaseGeneric : BaseGeneric<int>
{
public static new int DoStuff()
=> 789;
}
Now to call the DoStuff() method I would like to use var result = BaseGeneric<int>.DoStuff();
When I run this code, result is 0 instead of 789. The debugger shows that the call will enter the DoStuff() from public class BaseGeneric<T> instead of SpecializedFromBaseGeneric.
What am I doing wrong?
Later edit
I also tried to create specialization in the below format but that does not even compile:
public class BaseGeneric<T> where T : int
{
public static T DoStuff()
=> 789;
}
I want to do several specializations and use the call similar to the one specified above for int data type BaseGeneric<int>.DoStuff(). And for each specialization use the same syntax where only data type is changed but different implementation is used (eg: for string that would be BaseGeneric<string>.DoStuff()). How to achieve this behaviour?
public class BaseGeneric<T> where T : IConvertible
{
public static T DoStuff()
{
if (typeof(T) == typeof(int))
{
return (T)(object)789;
}
if (typeof(T) == typeof(string))
{
return (T)(object)"ss";
}
return default(T);
}
}
However, as the asnwer here suggests, this is brittle, and doesn't cover every possible usage.
var result = BaseGeneric<int>.DoStuff()
This one calls the function of a base class. It returns new T(), that equals new int(), that equals zero.
var result = SpecializedFromBaseGeneric.DoStuff()
This one will return what you need.

Best way to handle creation of large number of subtype objects

I have a base Message class, and around 100 different subtype classes of Message that represent each type of message that can be processed. What I am currently considering doing is using a giant switch statement to create the message object. For example:
switch (MsgType)
{
case MessageType.ChatMsg:
Msg = new MsgChat(Buf);
break;
case MessageType.ResultMsg:
Msg = new MsgResult(Buf);
break;
... // 98 more case statements
}
Msg.ProcessMsg(); // Use a polymorphic call to process the message.
Is there a better way to do this? If so, can you show an easy code example.
EDIT
So, I tried doing this:
public class Test
{
public Test()
{
IEnumerable<Type> myEnumerable = GetTypesWith<MyAttribute>(true);
}
IEnumerable<Type> GetTypesWith<TAttribute>(bool inherit)
where TAttribute : System.Attribute
{
return from a in AppDomain.CurrentDomain.GetAssemblies()
from t in a.GetTypes()
where t.IsDefined(typeof(TAttribute), inherit)
select t;
}
}
This appears to work in that myEnumerable now contains all 100 of the message subtypes, plus the base Message type as well. However, while I don't mind using reflection at the beginning of the program to load the types, using it to access the proper object in real time might be too slow. So, I would like to try out using a delegate.
The example in the comment below from #Mark Hildreth:
"So, you'd have a dictionary of >. Then, your mappings would be mappings[MessageType.ChatMsg] = x => new MsgChat(x);"
There are a couple of ways to interpret this code. One idea is to remove all 100 subclasses and just use one massive class with 100 delegate methods. That is a distant 2nd choice. The other idea and my first choice is for the above code to somehow create a message subclass object. But, I don't quite understand how it would do this. Also, it would be nice to keep the above technique in my Test class of getting all the types or delegates without having to write all 100 of them. Can you or anyone else explain how this can be done?
Instead using a giant switch statement, you can define a Dictionary to map each MessageType value to its defined Message derived class and creates an instance using this mapping data.
Dictionary definition:
Dictionary<int, Type> mappings = new Dictionary<int, Type>();
mappings.Add(MessageType.ChatMsg, typeof(MsgChat));
mappings.Add(MessageType.ResultMsg, typeof(MsgResult));
...
Dictionary consumption:
ConstructorInfo ctor = mappings[MessageType.ChatMsg].GetConstructor(new[] { typeof(Buf) });
Message message = (Message)ctor.Invoke(new object[] { Buf });
Note that I don't compiled this code to verify if is correct or not. I only want to show you the idea.
EDIT
There is my new answer to improve the first one. I'm thinking on your edited question, using given ideas from #MikeSW and #Mark Hildreth.
public class FactoryMethodDelegateAttribute : Attribute
{
public FactoryMethodDelegateAttribute(Type type, string factoryMethodField, Message.MessageType typeId)
{
this.TypeId = typeId;
var field = type.GetField(factoryMethodField);
if (field != null)
{
this.FactoryMethod = (Func<byte[], Message>)field.GetValue(null);
}
}
public Func<byte[], Message> FactoryMethod { get; private set; }
public Message.MessageType TypeId { get; private set; }
}
public class Message
{
public enum MessageType
{
ChatMsg,
}
}
[FactoryMethodDelegate(typeof(ChatMsg), "FactoryMethodDelegate", Message.MessageType.ChatMsg)]
public class ChatMsg : Message
{
public static readonly MessageType MessageTypeId = MessageType.ChatMsg;
public static readonly Func<byte[], Message> FactoryMethodDelegate = buffer => new ChatMsg(buffer);
public ChatMsg(byte[] buffer)
{
this.Buffer = buffer;
}
private byte[] Buffer { get; set; }
}
public class TestClass
{
private IEnumerable<Type> GetTypesWith<TAttribute>(bool inherit) where TAttribute : Attribute
{
return from a in AppDomain.CurrentDomain.GetAssemblies()
from t in a.GetTypes()
where t.IsDefined(typeof(TAttribute), inherit)
select t;
}
[Test]
public void Test()
{
var buffer = new byte[1];
var mappings = new Dictionary<Message.MessageType, Func<byte[], Message>>();
IEnumerable<Type> types = this.GetTypesWith<FactoryMethodDelegateAttribute>(true);
foreach (var type in types)
{
var attribute =
(FactoryMethodDelegateAttribute)
type.GetCustomAttributes(typeof(FactoryMethodDelegateAttribute), true).First();
mappings.Add(attribute.TypeId, attribute.FactoryMethod);
}
var message = mappings[Message.MessageType.ChatMsg](buffer);
}
}
You're on a right track and using a dictionary is a good idea. If reflection is too slow you can use expressions, like this (I'm assuming you decorate the Messages classes with a MessageTypeAttribute).
public class Test
{
public Test()
{
var dict=new Dictionary<MessageType,Func<Buffer,Mesage>>();
var types=from a in AppDomain.CurrentDomain.GetAssemblies()
from t in a.GetTypes()
where t.IsDefined(MessageTypeAttribute, inherit)
select t;
foreach(var t in types) {
var attr = t.GetCustomAttributes(typeof (MessageTypeAttribute), false).First();
dict[attr.MessageType] = CreateFactory(t);
}
var msg=dict[MessageType.Chat](Buf);
}
Func<Buffer,Message> CreateFactory(Type t)
{
var arg = Expression.Parameter(typeof (Buffer));
var newMsg = Expression.New(t.GetConstructor(new[] {typeof (Buffer)}),arg);
return Expression.Lambda<Func<Buffer, Message>>(newMsg, arg).Compile();
}
}

In C#, How to create a define and use a class hierarchy derived from an enum value?

Given an enum type:
public enum Work
{
Normal,
Extended
}
What I would like to do is the following.
public abstract class Builder<T>
{
public static Builder<T> GetBuilder<T> (T work)
{
return new Builder<T> ();
}
}
public class BuilderNormal : Builder<Work.Normal>
{
}
public class BuilderExtended : Builder<Work.Extended>
{
}
I specifically want to avoid using a switch/case in Builder or using a mapping that I would need to maintain when I would add a new enum value to Work, i.e. I could do this
public abstract class Builder
{
public static Builder GetBuilder (Work work)
{
switch (work)
{
case Work.Normal:
return new BuilderNormal ();
case Work.Extended:
return new BuilderExtended ();
default:
throw new ...
}
}
}
So, basically, I want to create an instance of a class depending on an enum value and the class must be a child class of an abstract class.
You can't in the way you've designed, basically. Generic type parameters are always for types, not values.
What you can certainly do is maintain a single Dictionary<Work, Func<Builder>> to allow you to basically register factories. That will avoid the switch statement, but it's still somewhere that you could forget to add values.
I'd rely on unit tests to avoid the problem though - write a test which checks that you can create a Builder for every value within the enum; then if you ever add a value to the enum without adding a mapping, your test will fail.
EDIT: Another option would be to add an attribute to the enum values to say which builder type corresponds to that value. You'd then need to extract that type with reflection and instantiate it that way.
You could do something pointless, crazy and slow like
public abstract class Builder
{
public static TBuilder GetBuilder<TBuilder>() where TBuilder : Builder
{
var ctors = typeof(TBuilder).GetConstructors(
BindingFlags.Instance |
BindingFlags.NonPublic |
BindingFlags.Public);
var matchingCtor = ctors.Single(
ci =>
{
var paramInfo = ci.GetParameters();
if (paramInfo.Length != parameters.Length)
{
return false;
}
return !paramInfo.Where((t, i) =>
t.ParameterType != parameters[i].GetType()).Any();
});
return (TBuilder)matchingCtor.Invoke(parameters);
}
}
which would give you a kind of static generic instance constructor, so you could do,
var builderNormal = Builder.GetBuilder<BuilderNormal>();
but, why not just call the instance constructor directly?

Casting generic type instances created using Reflection

I'm creating instances of a generic type using reflection:
public interface IModelBuilder<TModel>
{
TModel BuildModel();
}
public class MyModel
{
public string Name { get; set; }
}
public class MyModelBuilder : IModelBuilder<MyModel>
{
public MyModel BuildModel()
{
throw new NotImplementedException();
}
}
At runtime all we know is the Type of model e.g. MyModel. I can find instances of the relevant model builder like so:
var modelBuilders = from t in Assembly.GetExecutingAssembly().GetTypes()
from i in t.GetInterfaces()
where i.IsGenericType
&& i.GetGenericTypeDefinition() == typeof(IModelBuilder<>)
&& i.GetGenericArguments()[0] == modelType
select t;
var builder = Activator.CreateInstance(modelBuilders.First());
But I'm not sure how I can then cast the instance as IModelBuilder<TModel> so I can call and work with the result of BuildModel().
Since modelType is just a Type instance, you can't do that automatically, since there is no non-generic API available. Various options:
1: use reflection, for example (untested)
object builder = Activator.CreateInstance(...);
var model=builder.GetType().GetMethod("BuildModel").Invoke(builder,null);
2: cheat with dynamic:
dynamic builder = Activator.CreateInstance(...);
var model = builder.BuildModel();
3: make a non-generic version of IModelBuilder, and use that
Note that 1 & 2 rely on a public implementation of the interface, and will fail for a (perfectly legal) explicit interface implementation. For "1", you can fix this via:
var model = typeof(IModelBuilder<>).MakeGenericType(modelType)
.GetMethod("BuildModel").Invoke(builder);
A final sneaky option is to flip from a non-generic method into a generic method, so inside the generic method you can use all the members directly. There's a lazy way to do that via dynamic:
interface ISneaky<T>
{
T Foo { get; }
}
class Sneaky<T> : ISneaky<T>
{
T ISneaky<T>.Foo { get { return default(T); } }
}
class Program
{
static void Main()
{
Execute(typeof(int));
}
static void Execute(Type t)
{
dynamic obj = Activator.CreateInstance(
typeof(Sneaky<>).MakeGenericType(t));
// crafy hack to flip from non-generic code into generic code:
Evil(obj);
}
static void Evil<T>(ISneaky<T> sneaky)
{ // in here, life is simple; no more reflection
Console.WriteLine("{0}: {1}", typeof(T).Name, sneaky.Foo);
}
}

C# Generic T Class TypeOf, is this possible?

I have a class that is generic. Class<T> and depending in the switch statement in the calling code it can be class<int> class<string> class<decimal>
The the method that returns this returns it as an object because the calling code has no idea what it is until after it is set.
Is there a way to do this once I get the object back from the function?
load(object result)
{
Type t = result.GetType().GetGenericArguments()[0];
Class<t> x = (Class<t>) result;
}
Or do I have to set up an a check to check for each type it can be. If int then Class<int>, etc...
EDIT:
Here is what I am trying to do, actual code:
public class ReportResult<TP>
{
public ReportResult()
{
ReportHeaders = new List<ReportHeader>();
ReportViews = new List<IDataAttributeChild<TP>>();
}
public List<ReportHeader> ReportHeaders {get;set;}
public List<IDataAttributeChild<TP>> ReportViews {get;set;}
}
BAL
public object GetReportData(ReportProcedureNameEventArg procedureNameEventArg)
{
object result = null;
switch (procedureNameEventArg.SelectedNode.Class)
{
case ReportClass.Count:
var r = new ReportResult<int>
{
ReportViews = GetCountByReport(procedureNameEventArg),
ReportHeaders = GetReportHeaders(procedureNameEventArg.SelectedNode.ReportViewId)
};
result = r;
break;
case ReportClass.List:
break;
case ReportClass.Date:
var r = new ReportResult<datetime>
{
ReportViews = GetDateSummaryReport(procedureNameEventArg),
ReportHeaders = GetReportHeaders(procedureNameEventArg.SelectedNode.ReportViewId)
};
result = r;
break;
default:
throw new ArgumentOutOfRangeException();
}
return result;
}
The GUI
public void LoadTreeResult(object result)
{
Type t = result.GetType().GetGenericArguments()[0];
ReportResult<?> fff = (ReportResult<?>)result;
dgResult.Columns.Clear();
foreach (var header in result.ReportHeaders)
{
dgResult.Columns.Add(
new DataGridTextColumn
{
Header = header.Header,
Binding = new Binding(header.Binding)
});
}
// This would also be a switch depending on a property coming
// back to now what class to cast to in order to populate the grid.
List<ReportCountByView> d = new List<ReportCountByView>();
foreach (var reportCountByView in result.ReportViews)
{
d.Add((ReportCountByView)reportCountByView);
}
dgResult.ItemsSource = d;
}
This is a layout of the class model in case it might help.
image of layout
Thanks.
if you are going to call the same operation on the instance 'x' after you resolve it you may think about using an interface, this will allow you to define the methods the object performs (and properties) without defining it's type.
your code may then end up looking something like this
public interface IMyInterface
{
void PerformOperation();
}
public class MyGeneric<T> : IMyInterface
{
T Value {get;set;}
MyGeneric(T val)
{
Value = val;
}
void PerformOperation
{
Console.WriteLine("T is {0}", typeof(T));
Console.WriteLine("Value is {0}", Value);
}
}
public void main(string[] args)
{
IMyInterface inst = null;
switch (args[0])
{
case "string":
inst = new MyGeneric("hello");
break;
case "int":
inst = new MyGeneric(7);
break;
case "decimal"
inst = new MyGeneric(18.9M);
break;
}
inst.PerformOperation();
}
What do you want to do with x later? Also, if you can architect it such that x will always be an instance of some baseclass, you could just cast it to the base class.
It depends on how you intend to use the generic types later on. string, int and decimal have no common base type other than object, but they do share some interfaces, so you could possibly choose something like Class<IComparable> if you want to sort them later on. Or you could declare generic constraints if you want to use multiple interfaces:
Class<T> where T : IEquatable<T>, IComparable<T>, IFormattable // and so on...
But what it seems like you're asking for doesn't seem possible. The entire premise of generics is to set the type at design time.
My Opinion
If the result is always being used to invoke same members of the class(es), then can make an interface and implement it to the different classes and get the result as the interface.
This way you will be able to used different classes yet some same members of the interface that are implemented in those classes
I think the best way to do this switch would be to actually implement seperate methods for your different types, and switch at the UI layer.
For example
public ReportResult<int> GetReportDataCount(ReportProcedureNameEventArg procedureNameEventArg)
public ReportResult<DateTime> GetReportDataDate(ReportProcedureNameEventArg procedureNameEventArg)
public void GetReportDataList(ReportProcedureNameEventArg procedureNameEventArg)
The "List" one is the one that really throws me off, because it returns null, otherwise I'd say do something like
public ReportResult<T> GetReportData<T>(ReportProcedureNameEventArg procedureNameEventArg) where T:struct (and then enforce the types programatically).
If you want to try it with dynamics, I think you could make it work that way basically by doing duck typing with the ReportResult, but It might get messy with your List mode in the mix too.

Categories