I have lots(+2000) of GUIDs(in some network class) and my program must find one of them when it receives a message and do the job associated with it.
the positive point is i have a hard-code generator, but the fastest way is my goal(and i don't know how to implement it).
my code should do something like this:
switch(received guid)
{
case guid1: do job 1; break;
case guid2: do job 2; break;
case guid3: do job 3; break;
case guid4: do job 4; break;
....
}
You could create a Dictionary with the Guid as the key and a delegate reference as the value. That would ensure fast lookups.
Create an interface for doing the Job, then implement 2000 classes which do the work, each of which knows its own guid. Then add the classes to a dictionary using its guid as the key. Then when you get the guid, you look the object up in the dictionary and call the method on the interface.
public interface IJobDoer
{
void DoJob();
Guid Guid{get;}
}
public class FirstJobType : IJobDoer
{
void DoJob()
{
/// whatever...
}
Guid Guid { get{return "insert-guid-here";}}
}
Use a hashtable which maps Guid to a delegate or a class that represents the task, such as Dictionary<Guid, Action> or Dictionary<Guid, Task>.
A Dictionary<Guid, JobDelegate> would probably be faster than a switch statement.
But you would have to profile to be sure.
I like to show a variation of the dictionary approach others already proposed. Building on this that solution, you could do the following.
1 Define a base class:
public abstract class JobDoer
{
public abstract void DoJob();
}
2 Define a attribute for decoration of job doers.
public sealed class JobDoerAttribute : Attribute
{
JobDoerAttribute(string jobDoerId)
{
this.JobDoerId = new Guid(jobDoerId);
}
public Guid JobDoerId { get; private set; }
}
3 Define the actual job doer classes that are decorated with that attribute. For instance:
[JobDoer("063EE2B2-3759-11DF-B738-49BB56D89593")]
public sealed class SpecificJobDoer : JobDoer
{
public override void DoJob()
{
// Do a specific job
}
}
4 Define a JobDoerFactory that enables retrieving JobDoer instances by their Id as it is defined in the attribute:
public static class JobDoerFactory
{
static Dictionary<Guid, JobDoer> cache;
static JobDoerFactory()
{
// Building the cache is slow, but it will only run once
// during the lifetime of the AppDomain.
cache = BuildCache();
}
public static JobDoer GetInstanceById(Guid jobDoerId)
{
// Retrieving a JobDoer is as fast as using a switch statement.
return cache[jobDoerId];
}
private static Dictionary<Guid, JobDoer> BuildCache()
{
// See implementation below.
}
}
In the BuildCache method, you can do the loading of JobDoer instances by using reflection.
private static Dictionary<Guid, JobDoer> BuildCache()
{
// This is a bit naive implementation; we miss some error checking,
// but you'll get the idea :-)
var jobDoers =
(from assembly in AppDomain.CurrentDomain.GetAssemblies()
from type in assembly.GetTypes()
where type.IsSubclassOf(typeof(JobDoer))
let attributes =
type.GetCustomAttribute(typeof(JobDoerAttribute), true)
where attributes.Length > 0
let attribute = attributes[0] as JobDoerAttribute
select new { attribute.JobDoerId, type }).ToArray();
var cache = new Dictionary<Guid, JobDoer>(jobDoers.Length);
foreach (jobDoer in jobDoers)
{
// Note that actually a single instance of the job doer is
// cached by ID. This means that every Job Doer must be
// thread-safe and usable multiple times. If this is not
// feasable, you can also create store a set of Func<JobDoer>
// objects that enable creating a new instance on each call.
cache[jobDoer.JobDoerId] =
(JobDoer)Activator.CreateInstance(jobDoer.type);
}
return cache;
}
I didn't test this code, so I don't know if it compiles, but I used this mechanism in a project a few years back. This way it is easy to define new classes, without the need to hook it up to some dictionary. It is done automatically at runtime.
This might look a bit like overkill, but if you have +2000 JobDoer classes, this could help you a lot.
Update:
Note that if you don't like the idea of the JobDoerAttribute, you can also implement it as abstract property on the abstract JobDoer class. However, I've found using an attribute makes the code very explicit and expressive.
Create a Dictionary with Guid And Action, and search over it.
Related
I have a need to create unique ID's for my objects which can be saved and loaded between application instances.
I have this working in my current implementation but it means each of my classes needs almost the same piece of code, therefore I decided to create a base class with this code in and then inherit from that. The code is below. The only issue I'm having is that because I have a static list in the base class, all inherited class types are getting added to the same list.
Therefore how can I change the code so that the List 'items' is a different list between types?
To clarify. If I have two classes list this:
Foo: UniqueObject
Bar: UniqueObject
I want to the Foo and Bar to have their own static item list
abstract class UniqueObject
{
static protected List<UniqueObject> items = new List<UniqueObject>();
static Random rnd = new Random();
int id;
public int Object_ID { get { return id; } }
protected UniqueObject()
{
id = generateUniqueID();
items.Add(this);
}
protected UniqueObject(int Object_ID)
{
// Ensure the passed ID is unique
if (!isIdUnique(Object_ID))
{
// if not it does not get added to the items list and an exception is thrown.
throw new ArgumentNullException("Object ID is not unique. Already being used by another object.");
}
// If we get here then must have been unique so add it.
items.Add(this);
}
/// <summary>
/// Generates the unique identifier.
/// </summary>
/// <returns>The unique ID</returns>
private int generateUniqueID()
{
// get a random number
int val = rnd.Next();
// check it is unique, if not get another and try again.
while (!isIdUnique(val))
{
val = rnd.Next();
}
return val;
}
/// <summary>
/// Checks that the passed ID is unique against the other
/// objects in the 'items' list.
/// </summary>
/// <param name="ID">The identifier.</param>
/// <returns></returns>
private bool isIdUnique(int ID)
{
foreach (UniqueObject c in items)
{
if (c.id == ID)
return false;
}
return true;
}
}
I believe I can achieve this using Generics so i could change the class and list to something like this:
abstract class UniqueObject<T>
{
static protected List<T> items = new List<T>();
But this gives other errors with the line items.Add(this).
Any help would be appriciated.
On your last remark about using generics, I guess you could do this:
abstract class UniqueObject<T> where T : class
And then
items.Add(this as T);
This should work, and this as T should never fail on runtime if you don't explicitly use UniqueObject<>.
I'm not sure about how I feel about advocating having static members on generic types (and you should not do that), but this should at least work
Update: yes, it seems to work
Recommendation
In my answer, I tried to answer exactly what you were asking. But with all this said, if all you need is a unique ID for your objects and checking if it's not duplicated when you create them, you could:
Use a GUID, and forget about checking. GUID collisions are theoretically possible.... but will it happen? Under normal conditions, more likely not. Even if you created a trillion GUIDs in a year, there's a higher chance your program will crash by a meteorite striking the computer several times before you find a duplicate
Still, if you want to check it and make absolutely sure (which is a fair thing to do, actually), this could be way easier, and you don't need to store a list of the whole objects per-type to do this... see this simple base class, which will do what you want in a similar way you are doing it:
abstract class UniqueObject : IDisposable
{
static protected HashSet<Guid> Guids = new HashSet<Guid>();
Guid _id;
public Guid ObjectID { get { return _id; } }
protected UniqueObject()
{
do
{
_id = Guid.NewGuid();
} while(Guids.Contains(_id));
Guids.Add(_id);
}
protected UniqueObject(Guid guid)
{
if(Guids.Contains(guid))
throw new ArgumentNullException("Object ID is not unique. Already being used by another object.");
_id = guid;
}
// Make a better implementation of IDisposable
public void Dispose()
{
guids.Remove(_id);
}
}
And that's it. If you still want to use int instead of Guid, you could just change it to int, and have something like:
// static members
static protected Random rnd = new Random();
static protected HashSet<int> ids = new HashSet<int>();
// ... in the constructor:
do
{
_id = rnd.Next();
} while(ids.Contains(_id));
Which looks similar to what you had before
If you want an unique id that has the folowing properties:
1) Is unique in current app domain
2) Values are unique even when dealing with multiple instances of your application.
Then you need to consider one of these solutions:
1) Generate GUIDS
2) Have a unique "server" for your generated ids (a common server that can serve your ids)
3) If you know exactly how many application instances you have, you can define a "series" of unique ids for each instance.
And last, you need to abstract the notion of unicity into a separate service that you can move around in whatever tier / layer of your application. Your objects must NOT contain logic about unicity, this notion is a separate concern and you must be deal with it in other component. Please apply the separation of concerns pattern.
So this is my implementation (if I would be you)
public interface IEntityWithUniqueId
{
void SetUniqueId(string uniqueId);
string UniqueId { get; }
}
public interface IUniqueIdsProvider
{
string GetNewId();
}
public class UniqueObject : IEntityWithUniqueId
{
public string UniqueId { get; private set; }
void IEntityWithUniqueId.SetUniqueId(string uniqueId)
{
UniqueId = uniqueId;
}
}
public class MyObjects : UniqueObject
{
}
public class RemoteUniqueIdsProvider : IUniqueIdsProvider
{
public string GetNewId()
{
// calling a service ...., grab an unique ID
return Guid.NewGuid().ToString().Replace ("-", "");
}
}
public class UniqueObjectsFactory<T> where T : IEntityWithUniqueId, new ()
{
private IUniqueIdsProvider _uniqueIdsProvider;
public UniqueObjectsFactory(IUniqueIdsProvider uniqueIdsProvider)
{
_uniqueIdsProvider = uniqueIdsProvider;
}
public T GetNewEntity()
{
var x = new T();
x.SetUniqueId(_uniqueIdsProvider.GetNewId ());
return x;
}
}
I wrote a test method like this:
[TestClass]
public class UnitTest1
{
[TestMethod]
public void UniqueObjectTest()
{
var provider = new RemoteUniqueIdsProvider();
var factory = new UniqueObjectsFactory<MyObjects>(provider);
var entity = factory.GetNewEntity();
var entity2 = factory.GetNewEntity();
Assert.AreNotEqual(entity.UniqueId, entity2.UniqueId);
}
}
To explain what is above:
1) The interface IEntityWithUniqueId defines how an "unique" object must look like in your application, so it is an object that has an UniqueId property and also a special method: SetUniqueId. I didn't made the property UniqueId with get and set because "set" would be an infrastructure operation but get will be a developer API.
2) The interface IUniqueIdsProvider tells you how a unique ids provider will look like. It must have a simple method: GetNewId (); that serves you an unique Id. The implementation can be anywhere (on a server, locally, etc)
3) UniqueObject class. This class is the base class for all your unique objects.
4) UniqueObjectsFactory. This is the class that serves you new unique objects. When loading objects from disk, you must start from the asumption that you GENERATED unique ids, so when loading them you don't have to deal with checking unicity again.
In general terms, a program I'm making involves storing a small number of entries (probably less than 30 at any given time) which can be categorized. I want to allow these entries to be seen but not altered from outside the class using them. I made a class called Entry which could be modified and another called ReadOnlyEntry which is a wrapper for an Entry object. The easiest way to organize these Entry objects it seems is to create a List<List<Entry>>, where each List<Entry> is a category. But then exposing that data in a readonly way became messy and complicated. I realized I would have to have one object of each of the following types:
List<List<Entry>> data;
List<List<ReadOnlyEntry>> // Where each ReadOnlyEntry is a wrapper for the Entry in the same list and at the same index as its Entry object.
List<IReadOnlyCollection<ReadOnlyEntry>> // Where each IReadOnlyCollection is a wrapper for the List<ReadOnlyEntry> at the same index in data.
IReadOnlyCollection<IReadOnlyCollection<ReadOnlyList>> readOnlyList // Which is a wrapper for the first item I listed.
The last item in the list would be exposed as public. The first lets me change entries, the second lets me add or delete entries, and the third lets me add or delete categories. I would have to keep these wrappers accurate whenever the data changes. This seems convoluted to me, so I'm wondering if there's a blatantly better way to handle this.
Edit 1:
To clarify, I know how to use List.asReadOnly(), and the stuff I proposed doing above will solve my problem. I'm just interested in hearing a better solution. Let me give you some code.
class Database
{
// Everything I described above takes place here.
// The data will be readable by this property:
public IReadOnlyCollection<IReadOnlyCollection<ReadOnlyList>> Data
{
get
{
return readOnlyList;
}
}
// These methods will be used to modify the data.
public void AddEntry(stuff);
public void DeleteEntry(index);
public void MoveEntry(to another category);
public void AddCategory(stuff);
public void DeleteCategory(index);
}
You can use List<T>.AsReadOnly() to return ReadOnlyCollection<T>.
Also, you're torturing the List<T> class storing the data the way you are. Build your own hierarchy of classes which store your individual lists.
.NET collections should support covariance, but they don't support it themselves (instead some interfaces support covariance https://msdn.microsoft.com/ru-ru/library/dd233059.aspx). Covariance means List<Conctrete> behaves like subclass of List<Base> if Concrete is subclass of Base. You can use interfaces covariation or just use casting like this:
using System.Collections.Generic;
namespace MyApp
{
interface IEntry
{
}
class Entry : IEntry
{
}
class Program
{
private List<List<Entry>> _matrix = null;
public List<List<IEntry>> MatrixWithROElements
{
get
{
return _matrix.ConvertAll(row => row.ConvertAll(item => item as IEntry));
}
}
public IReadOnlyList<List<IEntry>> MatrixWithRONumberOfRows
{
get
{
return _matrix.ConvertAll(row => row.ConvertAll(item => item as IEntry));
}
}
public List<IReadOnlyList<IEntry>> MatrixWithRONumberOfColumns
{
get
{
return _matrix.ConvertAll(row => row.ConvertAll(item => item as IEntry) as IReadOnlyList<IEntry>);
}
}
public IReadOnlyList<IReadOnlyList<IEntry>> MatrixWithRONumberOfRowsAndColumns
{
get
{
return _matrix.ConvertAll(row => row.ConvertAll(item => item as IEntry));
}
}
public void Main(string[] args)
{
}
}
}
Thanks to Matthew Watson for pointing on errors in my previous answer version.
You could make an interface for Entry which contains only getters; you would expose elements via this interface to provide read-only access:
public interface IEntry
{
int Value { get; }
}
The writable implementation would be simply:
public sealed class Entry : IEntry
{
public int Value { get; set; }
}
Now you can take advantage of the fact that you can return a List<List<Entry>> as a IReadOnlyCollection<IReadOnlyCollection<IEntry>> without having to do any extra work:
public sealed class Database
{
private readonly List<List<Entry>> _list = new List<List<Entry>>();
public Database()
{
// Create your list of lists.
List<Entry> innerList = new List<Entry>
{
new Entry {Value = 1},
new Entry {Value = 2}
};
_list.Add(innerList);
}
public IReadOnlyCollection<IReadOnlyCollection<IEntry>> Data => _list;
}
Note how simple the implementation of the Data property is.
If you need to add new properties to IEntry you would also have to add them to Entry, but you wouldn't need to change the Database class.
If you're using C#5 or earlier, Data would look like this:
public IReadOnlyCollection<IReadOnlyCollection<IEntry>> Data
{
get { return _list; }
}
I have data from multiple organisations (police, fire, office) that need output in different formats.
To achieve this, I defined the following (this is a little simplified):
Transaction class -
"Success" indicator - Boolean.
"Type of department"- String or Enum.
A class which can be of any type - Police, Fire or Office (My question is on this as you will see).
A GenerateOutput() method - to handle generation of file formats.
Police class
Age - String
VehicleNumber - Integer
Supervisor - String
Fire class
Name - String
FireEngineNumber - Integer
County - Enum
WorkTimings - Enum
Office Class
Age - String
DeskNumber - Integer
Department - String
PayScale - Enum
IsManagement - Bool
As you can see, the Police, Fire and Office classes dont share anything in common and are primarily intended as data carrying entities. I intend to use a Factory to return an appropriate generic (not a C# generic) Transaction object with the data (Transaction object with Police, Fire or Office data within it) and then pass the returned object to a Strategy pattern which determines the file format (CSV, Excel, or XML; specified in a configuration file) each one needs.
My problem is in the definition of the Transaction object.
What type does the class in "3." of the Transaction class need to be? The data for each org differs, there are no common members, I am unable to define a common class for all.
Is the overall design appropriate? What other designs should I consider?
Based on Peter's comments below:
I think using generics might work, I ran into a problem though. I would like to use a factory to return the object requested, using GetTransactionObject, as below. What should be the return type of GetTransactionObject to accomodate this.
class TransactionFactory
{
Dictionary<string, Type> typeClassLookup;
public TransactionFactory()
{
typeClassLookup = new Dictionary<string, Type>();
typeClassLookup.Add("Police", typeof(PoliceData));
typeClassLookup.Add("Fire", typeof(FireData));
}
Transaction<????> GetTransactionObject(string org)
{
if( typeClassLookup.TryGetValue(org, out typeValue))
{
switch (typeValue.ToString())
{
case "policeData":
transactionObject = new Transaction<PoliceData>() { Data = new PoliceData(), params = null};
case "FireData":
transactionObject = new Transaction<FireData>() {Data = new FireData(), params = null};
}
}
return transactionObject;
If the types really have nothing in common, then you need no explicit base class. System.Object suffices, just as with many other generic types (i.e. any generic type lacking a constraint).
In other words, you could declare as:
class Transaction<T>
{
public bool Success { get; private set; }
public T Entity { get; private set; }
public Transaction(bool success, T entity)
{
Success = success;
Entity = entity;
}
public void GenerateOutput() { /* something goes here */ }
}
Personally, I would avoid adding a "department type" member. After all, that's implicit from the type parameter T. But you could add that easily to the above if you want.
If and when you find that the types do have something in common, such that your Transaction<T> type needs to do more than simply hold onto an instance of one of those types (which is about all it can do without a constraint), then you will be able to put that commonality into an interface or base class (depending on the specific need), and specify that in a constraint for the Transaction<T> class.
Note that it's not clear what you mean for the GenerateOutput() to do, or how it should work. But assuming that you want output that is specific for each Entity value, it seems to me that that is your "something in common". I.e., it's not the Transaction<T> class at all that needs to implement that method, but rather each entity type. In that case, you have something like this:
interface IDepartmentEntity
{
void GenerateOutput();
}
class Office : IDepartmentEntity
{
public void GenerateOutput() { /* department-specific logic here */ }
}
// etc.
Then you can declare:
class Transaction<T> where T : IDepartmentEntity
{
public bool Success { get; private set; }
public T Entity { get; private set; }
public Transaction(bool success, T entity)
{
Success = success;
Entity = entity;
}
public void GenerateOutput() { Entity.GenerateOutput(); }
}
EDIT:
Per Prasant's follow-up edit, with a request for advice on the GetTransactionObject()…
The right way to do this depends on the caller and the context, a detail not provided in the question. IMHO, the best scenario is where the caller is aware of the type. This allows the full power of generics to be used.
For example:
class TransactionFactory
{
public Transaction<T> GetTransactionObject<T>()
where T : IDepartmentEntity, new()
{
return new Transaction<T>()
{
Data = new T(),
params = null
}
}
}
Then you call like this:
Transaction<FireData> transaction = factory.GetTransactionObject<FireData>();
The caller, of course already knowing the type it is creating, then can fill in the appropriate properties of the transaction.Data object.
If that approach is not possible, then you will need for Transaction<T> itself to have a base class, or implement an interface. Note that in my original example, the IDepartmentEntity interface has only one method, and it's the same as the GenerateOutput() method in the Transaction class.
So maybe, that interface is really about generating output instead of being a data entity. Call it, instead of IDepartmentEntity, something like IOutputGenerator.
In that case, you might have something like this:
class Transaction<T> : IOutputGenerator
{
// all as before
}
class TransactionFactory
{
public IOutputGenerator GetTransactionObject(string org)
{
if( typeClassLookup.TryGetValue(org, out typeValue))
{
switch (typeValue.ToString())
{
case "policeData":
transactionObject = new Transaction<PoliceData>() { Data = new PoliceData(), params = null};
case "FireData":
transactionObject = new Transaction<FireData>() {Data = new FireData(), params = null};
}
}
return transactionObject;
}
}
This is an inferior solution, as it means the caller can only directly access the IOutputGenerator functionality. Anything else requires doing some type-checking and special-case code, something that really ought to be avoided whenever possible.
Note: if the Transaction type has other members which, like the GenerateOutput() method, are independent of the contained type T here, and which would be useful to callers who don't know T, then a possible variation of the above is to not reuse the interface used for the department-specific data types, but instead declare a base class for Transaction<T>, named of course Transaction, containing all those members not related to T. Then the return value can be Transaction.
What type does the class in "3." of the Transaction class need to be?
To decouple your department classes from the various export types, I recommend you make the department classes implement a common interface. Something like this:
public interface Exportable {
// return a list of attribute names, values, and types to export
IList<Tuple<String, String, Type>> GetAttributes();
}
For example:
public class Police : Exportable {
public IList<Tuple<String, String, Type>> GetAttributes() {
// return list size 3 - attribute info for Age, VehicleNumber, Supervisor
}
}
Is the overall design appropriate? What other designs should I consider?
The Transaction class design doesn't seem well suited for this problem.
Consider an Export class with a method for each export type, each method which receives the attributes returned from the Exportable interface method. Basic outline:
public static class Export {
public static boolean CSV(IList<Tuple<String, String, Type>> attributes) {
// export attributes to CSV, return whether succeeded
}
public static boolean Excel(IList<Tuple<String, String, Type>> attributes) {
// export attributes to Excel, return whether succeeded
}
// same thing for XML
}
I'm looking to use "phantom types" to implement type-safe identifiers. There's a question here about doing this in F#.
I'd like to do this in C#. How?
I've got a solution (which has problems), so I'll post it as a possible answer to see if anyone can improve it.
Why not make it a sealed class with its constructor private?
public sealed class Id<TDiscriminator>
{
private Id() { }
//some static methods
}
I've come up with the following:
struct Id<TDiscriminator>
{
private readonly Guid _id;
private Id(Guid id)
{
_id = id;
}
public Guid Value
{
get { return _id; }
}
public static Id<TDiscriminator> NewId()
{
return From(Guid.NewGuid());
}
public static Id<TDiscriminator> From(Guid id)
{
return new Id<TDiscriminator>(id);
}
public static readonly Id<TDiscriminator> Empty = From(Guid.Empty);
// Equality operators ellided...
}
...which I can use as follows:
class Order { /* empty */ }
class Customer { /* empty */ }
void Foo()
{
var orderId = Id<Order>.NewId();
var customerId = Id<Customer>.NewId();
// This doesn't compile. GOOD.
bool same = (orderId == customerId);
}
I don't particularly want concrete classes for the discriminator, because I don't want anyone instantiating them.
I could get around that by using an interface or an abstract class. Unfortunately, these can still be derived from and instantiated.
C# won't let you use a static class as a type argument. I can't say that I'm totally happy with the answers to that question, because the answers basically say "just because".
How about?
public sealed class Order
{
private Order() {}
}
public static sealed class Id<T>
{
// ...
}
I think that's exactly what you say. No one (except some special cases) can construct it and no one can inherit from it.
Well, as far as I could understand, you would like to provide a mechanism for distinguishing different types by a custom identifier object. I think you are almost near a working solution. In .NET when having a generic class, each substitution of the generic argument (or each unique combination of the generic arguments, if more than one) creates a unique type in the runtime. In your code Id<Order> and Id<Customer> are two distinct types. The NewId() method returns an instance of Id<Order> for the orderId and Id<Customer> for the customerId variables. The two types do not implement the == operator and therefore cannot be compared. Moreover, such comparison would be difficult to implement, since you cannot determine all possible uses of the Id<TDsicriminator> - you cannot guess what type will the TDsicriminator be substituted with.
1
A fast and simple solution will be to do this:
class Order { /* skipped */ }
class Customer { /* skipped */ }
void Foo()
{
var orderId = Id<Order>.NewId();
var customerId = Id<Customer>.NewId();
bool sameIds = (orderId.Value == customerId.Value); // true
bool sameObjects = orderId.Equals(customerId); // false
}
Since the Value properties are both of the Guid type, comparison is possible.
2
If you need however, to implement the == operator, or some sort of equality comparisons for instances of Id<TDisciminator>, the approach will be different. What comes up to my mind is the following:
public abstract class IdBase
{
public abstract Guid Value { get; protected set; }
public static bool operator == (IdBase left, IdBase right)
{
return left.Value == right.Value;
}
}
public sealed class Id<TDiscriminator> : IdBase
{
// your implementation here, just remember the override keyword for the Value property
}
Many people would not recommend the second approach though, since different implementations of IdBase may happen to have the same Value property (if you used the constructor that passes an existing ID). For instance:
var guid = Guid.NewGuid();
var customerID = Id<Customer>.From(guid);
var orderID = Id<Order>.From(guid);
Here (customerID == orderID) will then return true which is probably not what you want.
Shortly, in such a case, two different types will count as equal, which is a big logical mistake, so I'd stick to the first approach.
If you need Id<Customer>.Value to always be different than Id<Order>.Value, because of the different generic arguments (Customer is different than Order), then the following approach will work:
public sealed class Id<in TDiscriminator>
{
private static readonly Guid _idStatic = Guid.NewGuid();
private Id()
{
}
public Guid Value
{
get { return _idStatic; }
}
}
Notice the in keyword used here. This is applicable for .NET 4.0 where generics can be covariant and ensures that your class uses contravariant generics. (see http://msdn.microsoft.com/en-us/library/dd469487.aspx). In the above code, the _idStatic field will have a unique value for every different type supplied as a generic argument.
I hope this info is helpful.
I have a solution that works, but for educational purposes I want to understand if there is a better/cleaner/right way to do it.
Problem: In my "client" app I have a dictionary Dictionary<String, PremiseObject> where the key (String) is a immutable URL to a resource (it's actually a REST URL). PremiseObject is the base type of a whole set of derived classes; thus the Dictionary actually contains a family of classes all derived from PremiseObject.
A key requirement is I want to try to 'guarantee' that no PremiseObjects get created OUTSIDE of the dictionary.
Solution: I have the following function for getting a object out of the dictionary. It either accesses the existing instance, or if it does not exist creates it:
public PremiseObject GetOrCreateServerObject(string premiseObjectType, string location)
{
PremiseObject po = null;
if (!premiseObjects.TryGetValue(location, out po))
{
string classname;
// Create an instance of the right PremiseObject derived class:
po = // gobbly-gook that is not relevant to this question.
premiseObjects.Add(location, po);
}
else
{
Debug.WriteLine("Already exists: {0}", location);
}
return po;
}
Callers do this:
DoorSensor door =
(DoorSensor)server.GetOrCreateServerObject("DoorSensor",
"http://xyz/FrontDoor");
Works great. But I think there's a pattern or design that would elegantly allow me to encapsulate the "single-instance of each object contained in the dictionary" more.
For example, callers could do this:
DoorSensor door = null;
if (!server.ServerObjects.TryGetValue("DoorSensor",
"http://xyz/FrontDoor",
out door))
Debug.WriteLine("Something went very wrong");
I'm not really what to call this pattern. My ServerObjects are "single-instanced" by location. And my GetOrCreateServerObject is like a factory that lazy creates.
But it's possible for instances to be created that don't get put into the dictionary, which could lead to problems.
Like I said, what I have works... Cheers!
UPDATE 1/26/2011 10:13PM -
I just realized a potential problem: On the server side the object represented by a location/URL can actually be multi-inherited. It is THEORETICALLY possible for an object to be both a DoorSensor and an DigitalRelay.
I currently don't care about any of those cases (e.g. for garage doors I simplified my example above; there really is no DoorSensor I exposed, just a GarageDoorOpener which includes BOTH properties for sensing (e.g. Status) and actuation (e.g. Trigger). But this puts a wrinkle in my whole scheme if I were to care. Since this project is just for me :-) I am going to declare I don't care and document it.
I would propose the following simple idea:
PremiseObject's constructor is declared internal.
A special factory object is responsible for creating (or returning an already created) instances. The dictionary is a part of the factory.
Clients are located in another assembly.
This way PremiseObjects can be created by clients only through the factory. This way you can guarantee that only single instance of object exists for each location.
A variant of the idea would be to declare the PremiseObject's constructor private, and declare the factory a friend; but (unlike C++) C# doesn't have a friend notion.
Ok you can probably avoid a parameter and a cast (in the consumer code any way) with a generic method.
public abstract class PremiseObject
{
protected PremiseObject()
{
}
public string Location { get; set; }
public static void GetSensor<T>(string location, out T sensor)
where T : PremiseObject, new()
{
PremiseObject so;
if(_locationSingltons.TryGetValue(location, out so))
{
sensor = (T) so; // this will throw and exception if the
// wrong type has been created.
return;
}
sensor = new T();
sensor.Location = location;
_locationSingltons.Add(location, sensor);
}
private static Dictionary<string, PremiseObject> _locationSingltons
= new Dictionary<string, PremiseObject>();
}
Then the calling code looks a bit nicer:
DoorSensor frontDoor;
PremiseObject.GetSensor("http://FrontDoor/etc", out frontDoor);
So I like that calling convention - if you want to stay away from throwing an exception you can change the return type to bool and indicate failure that way. Personally I wouls say that an exception is what you want.
You may prefer the call without the out parameter - but if you do that then you have to supply the type to the method call - anyway defining the factory method would look like this:
public static T GetSensor<T>(string location) where T : PremiseObject, new()
{
PremiseObject so;
if (_locationSingltons.TryGetValue(location, out so))
{
return (T)so; // this will throw and exception if the
// wrong type has been created.
}
T result = new T();
result.Location = location;
_locationSingltons.Add(location, result);
return result;
}
Then the calling code looks like this:
var frontDoor2 = PremiseObject.GetSensor<DoorSensor>("http://FrontDoor/etc");
I like both these approaches because nothing has to be repeated. The type of the PremiseObject only gets stated once - there is no need for a string defining the type.
If you want to be really, really sure that no instances of PremiseObject get created that aren't placed in the dictionary, you could make the constructors all private, and create a static constructor (for each subclass) that took as a parameter the Dictionary object you're referring to. This static constructor would check the dictionary object to make sure that there wasn't an existing instance, and then return either the new or the existing instance as required. So something like this:
public class PremiseObject
{
public static Dictionary<string, PremiseObject> PremiseObjects { get; private set; }
static PremiseObject()
{
PremiseObjects = new Dictionary<string, PremiseObject>();
}
}
public class DerivedPremiseObject : PremiseObject
{
private DerivedPremiseObject()
{
}
public static DerivedPremiseObject GetDerivedPremiseObject(string location)
{
DerivedPremiseObject po = null;
if (!PremiseObject.PremiseObjects.TryGetValue(location, out po))
{
po = new DerivedPremiseObject();
PremiseObject.PremiseObjects.Add(location, po);
}
return po;
}
}
And there are a variety of similar strategies you could use. The key is to somehow make the constructor private and only allow access to the constructor through a static method that enforces the logic of the class construction.
Perhaps you could make PremiseObject a singleton, then you wouldn't have to worry about each object in the dictionary beign a single instance?
In the general case, setting access modifiers on your constructors should do the trick of not allowing anyone external to create the objects (barring reflection). However, these would need to be internal, so anything else in the assembly would be able to instantiate them.
I suspect many of your requirements may be met by using an off the shelf dependency injection container that supports singleton instances. It feels close, but maybe not quite the same. (possibly StrutureMap, Ninject, Castle Windsor, or Unity in no particular order)