I'm trying to implement an identity map using generics. I have an abstract class, Entity, and a derivation constraint on my map for Entity. Since my map needs to be able to instantiate entities, my map also has a constructor constraint.
However, for the map to be useful, Entity subclasses should not be able to be instantiated from client code, which means I would want an internal constructor and no public constructors. This conflicts with the constructor constraint, though.
Is there something I'm missing? Is there some way of refactoring this to get the desired result?
The following code compiles as-is but, ideally, Entity's subclasses' constructors would be internal:
public abstract class Entity
{
public int Id { get; protected internal set; }
}
public sealed class Widget : Entity
{
// Client code should not be allowed to instantiate entities.
// But the constraints on EntityMap require that entities have
// a public constructor.
public Widget() { }
}
public sealed class Gadget : Entity
{
public Gadget() { }
}
// The new() constraint is required so that Get() can instantiate Ts.
public class EntityMap<T> where T : Entity, new()
{
private Dictionary<int, T> _entities = new Dictionary<int, T>();
private object _getLock = new object();
public T Get(int id)
{
lock (_getLock)
{
if (!_entities.ContainsKey(id))
_entities.Add(id, new T() { Id = id });
}
return _entities[id];
}
// Client code should not be allowed to instantiate maps.
internal EntityMap() { }
}
// Ideally, the client would only be able to obtain Entity
// references through EntityMaps, which are only accessible
// through the ApplicationMap.
public static class ApplicationMap
{
public static EntityMap<Widget> Widgets = new EntityMap<Widget>();
public static EntityMap<Gadget> Gadgets = new EntityMap<Gadget>();
}
Instead of requiring a constructor constraint, pass a Func<T> to the map constructor. That way the constructor can be internal, but the map can still effectively call it:
public class EntityMap<T> where T : Entity
{
private readonly Dictionary<int, T> _entities = new Dictionary<int, T>();
private readonly object _getLock = new object();
private readonly Func<T> _entityGenerator;
public T Get(int id)
{
lock (_getLock)
{
T ret;
if (!_entities.TryGetValue(id, ret))
{
ret = entityGenerator();
newEntity[id] = ret;
ret.Id = id;
}
return ret;
}
}
internal EntityMap(Func<T> entityGenerator)
{
_entityGenerator = entityGenerator;
}
}
Then initialize it with:
EntityMap<Widget> widgetMap = new EntityMap(() => new Widget());
You could potentially make it a Func<int, T> instead and make the delegate responsible for creating an entity with the right ID. That way you could make your ID properly read-only, taking it as a parameter to the Entity constructor.
(I've taken the liberty of making your Get method more efficient, btw.)
Thanks to Jon, here's the working code:
public abstract class Entity
{
private readonly int _id;
public int Id
{
get { return _id; }
}
internal Entity(int id)
{
_id = id;
}
}
public sealed class Widget : Entity
{
internal Widget(int id) : base(id) { }
}
public sealed class Gadget : Entity
{
internal Gadget(int id) : base(id) { }
}
public class EntityMap<T> where T : Entity
{
private readonly Dictionary<int, T> _entities = new Dictionary<int, T>();
private readonly object _getLock = new object();
private readonly Func<int, T> _entityGenerator;
public T Get(int id)
{
lock (_getLock)
{
T entity;
if (!_entities.TryGetValue(id, out entity))
_entities[id] = entity = _entityGenerator(id);
return entity;
}
}
internal EntityMap(Func<int, T> entityGenerator)
{
_entityGenerator = entityGenerator;
}
}
public static class ApplicationMap
{
public static readonly EntityMap<Widget> Widgets = new EntityMap<Widget>(id => new Widget(id));
public static readonly EntityMap<Gadget> Gadgets = new EntityMap<Gadget>(id => new Gadget(id));
}
Related
I am looking for a way to support multi level of inheritance for generic type constraint.
Common generic interface
public interface ICommon<T>
{
T OrignalData {get;set;}
string ChangeJson {get;set;}
T Merged {get;set;}
void Inject();
}
Common base class implements ICommon
public class Base <T>: ICommon<T>
{
public T OrignalData {get;private set;}
public string ChangeJson {get;set;}
public T Merged {get;private set;}
public void Inject(T orignal)
{
if (orignal == null)
return;
var settings = new JsonSerializerSettings
{
ObjectCreationHandling = ObjectCreationHandling.Auto
};
dynamic merged = orignal.Clone();
JsonConvert.PopulateObject(this.ChangeJson, merged, settings);
this.Merged = merged;
this.Orignal = orignal;
}
}
Department class inherits Base class
public class Deparment : Base<Deparment>
{
}
OrgnizationDepartment class inherits Deparment
public class OrgnizationDepartment : Deparment
{
}
class View expect ICommon must implement on passed calls
public class View<T> where T : ICommon<T>
{
//This class is totally dynamic to visualize any json data along with old and new value of requested json for any class like department or org..
}
Test
public class Test
{
public void TestConstraint()
{
//No error
var deptView = new View<Deparment>();
//Error as Base not directly implemented on OrgnizationDepartment
var orgView = new View<OrgnizationDepartment>();
}
}
how do I define my constraint that should support for multi level as well.
One way out of this would be "composition over inheritance".
Here is a naive example, that is still relatively close to your code:
using System;
using Newtonsoft.Json;
public class Program
{
public static void Main()
{
//No error
var deptView = new View<Deparment>();
//Formerly Error
var orgView = new View<OrgnizationDepartment>();
}
}
public interface ICommon<T> where T : ICloneable
{
// returns a tuple
(T,T,string) Inject(T original, string change);
}
public class Base <T>: ICommon<T> where T : ICloneable
{
// we can reuse this...
private readonly JsonSerializerSettings settings = new JsonSerializerSettings
{
ObjectCreationHandling = ObjectCreationHandling.Auto
};
public (T,T,string) Inject(T original, string change)
{
if (original is null)
return default;
// this forces T to implement ICloneable ... just saying...
dynamic merged = original.Clone();
JsonConvert.PopulateObject(change, merged, settings);
return (original, merged, change);
}
}
public class Deparment : ICloneable, ICommon<Deparment>
{
// could also be created in ctor. Maybe use Ctor injection.
private readonly Base<Deparment> common = new Base<Deparment>();
public object Clone(){return this;} // this is of course nonsense. Clone properly! I did this to avoid dotnetfiddle screaming at me.
public (Deparment, Deparment, string) Inject(Deparment original, string change){
return common.Inject(original, change);
}
}
public class OrgnizationDepartment : ICloneable, ICommon<OrgnizationDepartment>
{
private readonly Base<OrgnizationDepartment> common = new Base<OrgnizationDepartment>();
public object Clone() {return this;}
public (OrgnizationDepartment, OrgnizationDepartment, string) Inject(OrgnizationDepartment original, string change){
return common.Inject(original, change);
}
}
I have a basic architecture for 'orders' in my game - each order has a basic data type and an 'order processor' which performs some action based on the given data. For example 'move to this point.'
I'd like to have a tidy system where I can simply pass in order data and the correct order processor will kick in, in such a way that I can easily add new OrderData/OrderProcessor classes without modifying other classes or messing around with enums or casting, so it seems like generics are the way to go.
This is the current code I have. I'm drawing a blank for how to draw a connection in the 'OrderService' class between the correct 'OrderProcessor' and 'IOrderData' pairs. See inside the OrderService<T> class for more information:
public interface IOrderData
{
}
// an order processor reads data from an IOrderData object until the data object says stop
public abstract class OrderProcessor<T> where T : IOrderData
{
protected T m_currentData;
public virtual void Start(T data)
{
m_currentData = data;
}
}
////////////////////////
public class MoveOrderData : IOrderData
{
public Vector3 Destination { get; private set; }
}
public class MoveOrderProcessor : OrderProcessor<MoveOrderData>
{
public override void Start(MoveOrderData data)
{
base.Start(data);
}
}
////////////////////////
public class OrderService<T> where T : IOrderData
{
private Dictionary<System.Type, OrderProcessor<T>> m_processors = new Dictionary<System.Type, OrderProcessor<T>>();
private OrderProcessor<T> m_currentProcessor;
public void GiveOrder(IOrderData data)
{
// this is the main problem: I'm not sure how to say "the given data is type 'MoveOrderData' so find out which
// OrderProcessor class handles those and pass it in". A simple switch statement and cast would suffice here
// but I'd like to automate the process
}
}
A possible solution here can be a making an OrderService class non-generic, because it can handle a different types of orders/order processors (according to comments). Then maintain a Dictionary<Type, Action<object>>, which wraps Action<object> to call Start method from OrderProcessor<T>.
I've extended the original code a little bit to show how it can work
public interface IOrderData
{
}
public class MoveOrderData : IOrderData
{
public Vector3 Destination { get; private set; }
}
public class AttackOrderData : IOrderData
{
}
public abstract class OrderProcessor<T> where T : IOrderData
{
protected T CurrentData { get; set; }
public virtual void Start(T data)
{
CurrentData = data;
}
}
public class MoveOrderProcessor : OrderProcessor<MoveOrderData>
{
}
public class AttackOrderProcessor : OrderProcessor<AttackOrderData>
{
}
public class OrderService
{
private readonly Dictionary<Type, Action<object>> m_processors = new Dictionary<Type, Action<object>>();
public OrderService()
{
AddProcessor(new MoveOrderProcessor());
AddProcessor(new AttackOrderProcessor());
}
private void AddProcessor<T>(OrderProcessor<T> processor) where T : IOrderData
{
var action = (Action<T>)processor.Start;
m_processors.Add(typeof(T), obj => action((T)obj));
}
public void GiveOrder(IOrderData data)
{
var action = m_processors[data.GetType()];
action?.Invoke(data);
}
}
It causes a downcasting obj => action((T)obj), but it shouldn't be a problem, since your data is constrained to IOrderData interface. Example of the usage
var service = new OrderService();
service.GiveOrder(new MoveOrderData());
service.GiveOrder(new AttackOrderData());
i wasn't able to find a similar issue but feel free to redirect me if i just missed it.
I am trying to get familiar with the Repository pattern.
I'll give you an example of the code i'm trying to get to work unsuccessfully.
These are the classes and interfaces that represent the entity i'm using.
public class AbsObj
{
public string Code { get; set; }
}
public interface IAbsObj
{
bool Save();
}
public class User : AbsObj
{
public string Language{get; set;}
}
public class DbUser : User, IAbsObj
{
public bool Save()
{
return true;
}
}
Then to the repository Interface
public interface IRepository<T>
{
void Add(T value);
void Update(T value);
void Delete(T value);
}
The generic Repository
public class Repository<T> : IRepository<T> where T : AbsObj, IAbsObj
{
protected List<T> _lst;
public Repository()
{
_lst = new List<T>();
}
public void Add(T value)
{
}
public void Update(T value)
{
}
public void Delete(T value)
{
}
public bool Save()
{
for (int i = 0; i < _lst.Count; i++)
{
_lst[i].Save();
}
return true;
}
}
Then a more specific repository, which should handle the loading of the users from the db:
public class UserRepository<T> : Repository<T> where T : AbsObj, IAbsObj
{
public void Load()
{
DbUser us = new DbUser();
us.Code = "Cod";
us.Language = "IT";
_lst.Add(us);
}
}
I created the DBUser class just to have the freedom to create an XMLUser in the future which would handle a different type of saving.
It inherits from User which in turn inherits from AbsObj.
It implements IAbsObj.
Nonetheless i got a compile time error when i try to add to the list the DbUser object created, stating that it's impossible to convert from DBUser to T.
Given the constraints i tought it was possible: what am i missing here?
Thanks in advance for any help!
Your UserRepository definition could be:
public class UserRepository : Repository<DbUser>
{
....
}
But since you want to make it generic for XMLUser as well:
public class UserRepository<T> : Repository<T> where T: User, new()
{
public void Load()
{
User us = new T() as User;
us.Code = "Cod";
us.Language = "IT";
_lst.Add(us);
}
}
To use:
new UserRepostitory<DbUser>();
new UserRepostitory<XmlUser>();
EDIT: This question would be invalid in .NET 4 since it actually works as desired.
I have a Data class that must implement an interface like this:
public interface IData
{
IEnumberable<IOther> OtherList { get; }
IOther AddOther();
void RemoveOtherData(IOther data);
}
But I am stuck with declaring the actual member in Data
public class Data : IData
{
// desired, always return the same reference
public IEnumberable<IOther> OtherList { get { return _mOtherList } }
// Non persistent reference not desirable.
public IEnumerable<IOther> OtherList { get { return _mOtherList.Select(x => x as IOther); } }
List<IOther> _mOtherList = new List<Other>(); // error, type mismatch
List<Other> _mOtherList = new List<Other>(); // error, property return type mismatch
IEnumerable<IOther> _mOtherList = new List<Other>(); // ok, but cannot use List methods without casting.
}
What would be the best solution in this case?
public class Data : IData
{
public IEnumerable<IOther> OtherList { get; private set; }
List<Other> _mOtherList = new List<Other>();
public Data()
{
OtherList=mOtherList.Cast<IOther>();
}
}
On .net 4 IEnumerable<out T> is co-variant. i.e. a class that implements IEnumerable<Other> automatically implements IEnumerable<IOther> too. So could also simply write:
public class Data : IData
{
public IEnumerable<IOther> OtherList { get{return mOtherList;} }
List<Other> _mOtherList = new List<Other>();
}
But I'd avoid that, since it breaks encapsulation and allows outsiders to modify your list.
((List<Other>)MyData.OtherList).Add(...);
Other class must implement IOther interface and you don't need to cast.
When you declare _mOtherList, it's IEnumerable, so you can't use list methods. Declare it as a list.
public class Data : IData
{
List<IOther> _mOtherList = new List<Other>();
public IEnumberable<IOther> OtherList { get { return _mOtherList } }
IOther AddOther()
{
return null;
}
void RemoveOtherData(IOther data){}
}
Your Other class:
class Other : IOther
{
//some members
}
As IEnumerable is covariant this is fine:
public interface IInterface{}
public class ClassA : IInterface{}
public class ClassB
{
private readonly List<ClassA> _classAs;
public IEnumerable<IInterface> Data{ get { return _classAs; } }
}
I am quite new to the C# world and I apologize if the Question title not exactly match the content. But now to my Problem:
I have the following construct:
public interface IClass<TEnum>
{
Dictionary<TEnum, ISecondClass> dictionary { get; }
}
public abstract class ClassBase<TEnum> : IClass<TEnum>
{
public abstract Dictionary<TEnum, ISecondClass> dictionary { get; protected set; }
}
public class ConcreteClass : ClassBase<ConcreteClass.Concrete>
{
public override Dictionary<Concrete, ISecondClass> dictionary { get; protected set; }
public enum Concrete : ulong
{
}
}
public class OtherClass : ClassBase<OtherClass.Other>
{
public override Dictionary<Concrete, ISecondClass> dictionary { get; protected set; }
public enum Other : ulong
{
}
}
My goal is to instantiate all existing concrete classes based on it's enums, store all instances in a dictionary and later invoke some methods on each object.
I am not sure if this is even possible?
I am glad for any hint on this!
If I understand what you're trying to do, it sounds like a version of the Multiton Pattern. You may find it useful to research that.
From Wikipedia's example Multiton code:
class FooMultiton
{
private static readonly Dictionary<object, FooMultiton> _instances = new Dictionary<object, FooMultiton>();
private FooMultiton() {}
public static FooMultiton GetInstance(object key)
{
lock (_instances)
{
FooMultiton instance;
if (!_instances.TryGetValue(key, out instance))
{
instance = new FooMultiton();
_instances.Add(key, instance);
}
}
return instance;
}
}
This isn't directly pasteable into your class, but since you're looking for hints, I think it should point you in the right direction.
One word of caution about the above code: The method GetInstance will alter the dictionary if key isn't found. Personally, I associate the "Get" prefix with read-only methods. I'd either rename GetInstance or split it into two methods.
I'm not really sure what you mean by "instantiate all existing concrete classes based on it's enums", though. Can you clarify that?
Use Activator.CreateInstance() to create concrete classes' objects and store them into dictionary.
Pass your string classname from Enum and create dynamic class objects. Store them into Dictionary<Enum, ISecondClass>
myObject = (MyAbstractClass)Activator.CreateInstance("AssemblyName", "TypeName");
or
var type = Type.GetType("MyFullyQualifiedTypeName");
var myObject = (MyAbstractClass)Activator.CreateInstance(type);
While retrieving, based on your enum key, you know what type of instance value represents.
I don't understand a goal of the sample code, but you can write some thing like this:
public interface IClass
{
void MethodToDynamicInvoke();
}
public abstract class ClassBase<T>
: IClass
{
private Dictionary<Type, List<IClass>> instances = new Dictionary<Type, List<IClass>>();
public ClassBase()
{
List<IClass> list;
if (!instances.TryGetValue(typeof(T), out list))
{
list = new List<IClass>();
instances.Add(typeof(T), list);
}
list.Add(this);
}
public abstract void MethodToDynamicInvoke();
public void InvokeMetodOnClassesWithSameEnum()
{
List<IClass> list;
if (instances.TryGetValue(EnumType, out list))
{
foreach (var instance in list)
{
instance.MethodToDynamicInvoke();
}
}
}
}
public class ConcreteClass
: ClassBase<ConcreteClass.Concrete>
{
public ConcreteClass()
: base()
{
}
public override void MethodToDynamicInvoke()
{
throw new NotImplementedException();
}
public enum Concrete : ulong
{
}
}
public class OtherClass : ClassBase<OtherClass.Other>
{
public OtherClass()
: base()
{
}
public override void MethodToDynamicInvoke()
{
throw new NotImplementedException();
}
public enum Other : ulong
{
}
}