using lambda to extract member info via System.Reflection - c#

I am trying to use system Reflection to enable extraction of a class member (type int)
var CurrTblID = typeof(currProjData).GetMembers(
BindingFlags.Public |BindingFlags.Static
).Select(t => t.Name)...what expresssion should I put here?
this will expose an enumerator, with the interface iEnumerable and assign it to CurrTblID
so i could use foreach loop , to find which "table ID" Tid is the current one
How Can i get to a specific field name and find out its value without the foreach?
the Source for the question is in thecurrProjData class , shown below.
some background if needed for the answer :
in this code i am using a struct that enables setting Sql server Database table
with details for later use.
i couldnt find answer for that in sql server so i've made
a struct to hold a custom index - as a numeric ID for each table i will use in my application .
public class DBMetaDetails
{
public struct DbTable
{
public DbTable(string tableName, int tableId): this()
{
this.TableName = tableName;
this.TableID = tableId;
}
public string TableName { get; set; }
public int TableID { get; set; }
}
}
TableID is a custom numeric "id" i am using via that struct,
so this is how i could reference the SQL table by a custom "index" rather its database name .
public static class currProjData
{
static DBMetaDetails.DbTable CustomersMeta = new DBMetaDetails.DbTable();
static DBMetaDetails.DbTable TimesMeta = new DBMetaDetails.DbTable();
public static void SetTablesMetaDetails()
{
TimesMeta.TableID = HTtIDs.TblTimes;
TimesMeta.TableName = HTDB_Tables.TblTimes;
CustomersMeta.TableID = HTtIDs.TblCustomers;
CustomersMeta.TableName = HTDB_Tables.TblTimeCPAReport;
}
public static readonly int CustomersTid = CustomersMeta.TableID;
public static readonly string CustomersTblName = CustomersMeta.TableName;
public static readonly int TimesTid = TimesMeta.TableID;
public static readonly string TimesTblName = TimesMeta.TableName;
}

How Can i get to a specific field name and find out its value without the foreach?
Create a generic extension Method which will handle any object and then internally do a FirstOrDefault:
public static int ExtractIntProperty<T>( this T targetItem, string propertyName )
{
int result = 0;
var prop = targetItem.GetType()
.GetProperties()
.FirstOrDefault( prp => prp.Name == propertyName );
if (prop != null)
{
var val = prop.GetValue( targetItem, null );
if (val != null)
result = (int) val;
}
return result;
}
Then get the value as such (casting to show that it handles unknown objects)
object detail = (object) new DBMetaDetails.DbTable() { TableName = "Jabberwocky", TableID = 12 };
Console.WriteLine ( detail.ExtractIntProperty("TableID") ); // 12

Related

How to create DevExpress XPO dynamically with multiple primary-keys table?

I try example in this topic
https://github.com/DevExpress-Examples/XPO_how-to-create-an-xpclassinfo-descendant-to-dynamically-build-a-persistent-class-structure-e1729
But It only works for single primary key tables. So i searched more Found this:
https://github.com/DevExpress-Examples/XPO_how-to-create-persistent-classes-mapped-to-tables-with-a-composite-primary-key-at-runtime-e4606
Buts there's big different and I think its not satisfy because it speaking about composite key( one Key which have many columns)
So all I need please an example of creating XPO dynamically from SQL -Server Table:
My Table Schema as following
The XPOCollectionSource then binding to grid in server-mode… Thats all I need.
Code I Use
XPServerCollectionSource GetServerModeSourceForTable(IDbConnection connection, string tableName) {
XPDictionary dict = new ReflectionDictionary();
XPClassInfo classInfo = dict.CreateClass(dict.QueryClassInfo(typeof(LiteDataObject)),
tableName);
DBTable[] tables = ((ConnectionProviderSql)XpoDefault.GetConnectionProvider(connection,
AutoCreateOption.None)).GetStorageTables(tableName);
foreach (DBColumn col in tables[0].Columns) {
XPMemberInfo member = classInfo.CreateMember(col.Name, DBColumn.GetType(
col.ColumnType));
if (tables[0].PrimaryKey.Columns.Contains(col.Name))
member.AddAttribute(new KeyAttribute());
}
return new XPServerCollectionSource(new Session(XpoDefault.GetDataLayer(
connection, dict, AutoCreateOption.None)), classInfo);
}
At a glance. How to use XPServerCollectionSource with Dynamically created XPO object. with two primary keys.
https://github.com/DevExpress-Examples/XPO_how-to-create-persistent-classes-mapped-to-tables-with-a-composite-primary-key-at-runtime-e4606/blob/19.2.7%2B/CS/XpoConsoleApplication/XPComplexCustomMemberInfo.cs
This is a class must used. who need more details about that. I can help him for free.
Implementation can be like:
[NonPersistent]
public class XPDynamicObject : XPLiteObject
{
public XPDynamicObject(Session session) : base(session) {}
public XPDynamicObject(Session session, XPClassInfo classInfo) : base(session, classInfo) { }
}
Button_Click or any event :
XPDynamicObject.AutoSaveOnEndEdit = false;
ReflectionDictionary dic = new ReflectionDictionary();
var classInfo = dic.CreateClass(dic.GetClassInfo(typeof(XPDynamicObject)), "general.users");
// WE MUST get schema from database .... via ConnectionProviderSql this is only way
var provider = XpoDefault.GetConnectionProvider(MSSqlConnectionProvider.GetConnectionString("(local)", "testdb"), AutoCreateOption.None) as ConnectionProviderSql;
// Composite Key - this is only way to add composite key dynamically
XPComplexCustomMemberInfo user_key = new
XPComplexCustomMemberInfo(classInfo, "user_key", typeof(object), new KeyAttribute(), new PersistentAttribute(), new BrowsableAttribute(false));
user_key.AddSubMember("user_brn", typeof(int), new PersistentAttribute("user_brn"));
user_key.AddSubMember("user_num", typeof(int), new PersistentAttribute("user_num"));
var user_name = classInfo.CreateMember("user_name", typeof(string));
user_name.AddAttribute(new PersistentAttribute("user_name"));
dal = new SimpleDataLayer(dic, provider);
XPServerCollectionSource xpServerCollectionSource = new XPServerCollectionSource(session, classInfo); // XPServerCollectionSource Only Editable server-mode datasource via ALlowNew, AllowEdit, AllowRemove properties
GridControl.DataSource = xpServerCollectionSource ;
Full Cheat Sheet (Design-Time and Run-Time XPOs)
For Searching for Object by Key or Condition use following:
Edit: 2021-05-24
For those who asks about Associations with composite keys. Its really nightmare. By default Xpo doesn't provide that. instead you can use a Session.GetObjectByKey() in child-class and a new XPCollection in parent class. But actually its something little slowly that native way with an artificial key.
At a glance: Use Artifcial / Single Key Column for Better any ORM
compatibility. Otherwise It will be nightmare in database later. If
you for example support another or replace current ORM.
Here's a code for associations with composite keys. (Note that you need to convert it dynamically like above pictures. You maybe need to create custom XPMemberInfo and override GetValue() to return Session.GetObjectByKey() and create new XPCollection. (really bad stuff to do and worst ever and non-supported ever by Xpo. So Composite-Keys technically are bad way except if you need create Single Table bind it to grid. EX:- SalesOrderDetail table which doesn't have more child tables)
[Persistent("users")]
public class user : XPLiteObject
{
public user(Session session) : base(session) { }
public user(Session session, XPClassInfo classInfo) : base(session, classInfo) { }
[Key, Persistent]
public user_key user_key { get; set; }
[Persistent("user_name")]
public string user_name { get; set; }
private XPCollection<Trans> _trans;
public XPCollection<Trans> trans
{
get
{
if (_trans == null)
_trans = new XPCollection<Trans>(Session, CriteriaOperator.Parse($"user_brn = {user_key.user_brn} AND user_num = {user_key.user_num}"));
return _trans;
}
}
}
public class Trans : XPLiteObject
{
public Trans(Session session) : base(session) { }
public Trans(Session session, XPClassInfo classInfo) : base(session, classInfo) { }
[Key,Persistent("TransID")]
public int TransID { get; set; }
public int user_brn { get; set; }
public int user_num { get; set; }
public user user
{
get
{
var key = new user_key();
key.user_brn = 1;
key.user_num = 3;
var obj = Session.GetObjectByKey<user>(key, true);
return obj;
}
}
}
// Composite-Key
public struct user_key
{
[Persistent("user_brn")]
public int user_brn { get; set; }
[Persistent("user_num")]
public int user_num { get; set; }
}
A Dynamic run-time version from above model:
class XPCompositeAssociationMemberInfo : XPCustomMemberInfo
{
public XPCompositeAssociationMemberInfo(XPClassInfo owner, string propertyName, Type propertyType, XPClassInfo referenceType, bool nonPersistent, bool nonPublic) : base(owner, propertyName, propertyType, referenceType, nonPersistent, nonPublic)
{
}
public override object GetValue(object theObject)
{
XPDynamicObject val = theObject as XPDynamicObject;
if(val != null)
{
var user_num = val.GetMemberValue("user_num");
IdList vals = new IdList();
vals.Add(1);
vals.Add(user_num);
return val.Session.GetObjectByKey(ReferenceType, vals);
}
return val;
}
}
XPDynamicObject.AutoSaveOnEndEdit = false;
ReflectionDictionary dic = new ReflectionDictionary();
var userClassInfo = dic.CreateClass(dic.GetClassInfo(typeof(XPDynamicObject)), "users");
// WE MUST get schema from database .... via ConnectionProviderSql this is only way
var provider = XpoDefault.GetConnectionProvider(MSSqlConnectionProvider.GetConnectionString("(local)", "testdb"), AutoCreateOption.None) as ConnectionProviderSql;
//DBTable Table = provider.GetStorageTables("users")[0];
// Composite Key - this is only way to add composite key dynamically
XPComplexCustomMemberInfo user_key = new XPComplexCustomMemberInfo(userClassInfo, "user_key", typeof(object), new KeyAttribute(), new PersistentAttribute(), new BrowsableAttribute(false));
user_key.AddSubMember("user_brn", typeof(int), new PersistentAttribute("user_brn"));
user_key.AddSubMember("user_num", typeof(int), new PersistentAttribute("user_num"));
var user_name = userClassInfo.CreateMember("user_name", typeof(string));
user_name.AddAttribute(new PersistentAttribute("user_name"));
var transClassInfo = dic.CreateClass(dic.GetClassInfo(typeof(XPDynamicObject)), "Trans");
var TransID = transClassInfo.CreateMember("TransID", typeof(int), new KeyAttribute());
var user_brn = transClassInfo.CreateMember("user_brn", typeof(int));
var user_num = transClassInfo.CreateMember("user_num", typeof(int));
XPCompositeAssociationMemberInfo userMI = new XPCompositeAssociationMemberInfo(transClassInfo, "user", typeof(object), userClassInfo, true, false);
dal = new SimpleDataLayer(dic, provider);
Session session = new Session(dal);
XPServerCollectionSource xpServerCollectionSource = new XPServerCollectionSource(session, transClassInfo); // XPServerCollectionSource Only Editable server-mode datasource via ALlowNew, AllowEdit, AllowRemove properties
xpServerCollectionSource.DisplayableProperties = "TransID;user.user_key.user_num;user.user_name";
Finally, IMPORTANT !
Its really very very hard to achieve Composite-Keys cases at runtime
in any Xpo. Instead replace with Single Column Key(Identity or
Artificial one. GUID one etc.)
I don't know if this is what you want, but I'll share my code using XPInstantFeedbackSource.
You can get more information at How To Implement The Instant Feedback Mode Xpo
XPLiteObject LogXPOModel
[Persistent("log.t_log")]
public class LogXPOModel : XPLiteObject
{
[Key, DevExpress.Xpo.DisplayName("id")]
public long id { get; set; }
[Key, DevExpress.Xpo.DisplayName("recv_time")]
public long recv_time
...
}
Window MainWindow
public class MainWindow : Window
{
public XPInstantFeedbackSource SqliteXPInstantFeedbackSource
public MainWindow() {
...
SqliteXPInstantFeedbackSource = new XPInstantFeedbackSource();
SqliteXPInstantFeedbackSource.ObjectType = typeof(LogXPOModel);
SqliteXPInstantFeedbackSource.ResolveSession += SqliteXPInstantFeedbackSource_ResolveSession;
SqliteXPInstantFeedbackSource.DismissSession += SqliteXPInstantFeedbackSource_DismissSession;
View.Grid.ItemsSource = SqliteXPInstantFeedbackSource;
}
...
}
Like that — my table has two keys; and, it does not incur any problems.

Detecting mismatch between constructor parameter names and property names with immutable objects

Consider the following mutable object:
class SomePoco
{
public int Id{get;set;}
public string Name{get;set;}
}
Let's round trip it through Json.NET:
var p=new SomePoco{Id=4,Name="spender"};
var json=JsonConvert.SerializeObject(p);
var pr = JsonConvert.DeserializeObject<SomePoco>(json);
Console.WriteLine($"Id:{pr.Id}, Name:{pr.Name}");
All is good.
Now, let's make out POCO immutable and feed values via a constructor:
class SomeImmutablePoco
{
public SomeImmutablePoco(int id, string name)
{
Id = id;
Name = name;
}
public int Id{get;}
public string Name{get;}
}
... and round-trip the data again:
var p = new SomeImmutablePoco(5, "spender's immutable friend");
var json = JsonConvert.SerializeObject(p);
var pr = JsonConvert.DeserializeObject<SomeImmutablePoco>(json);
Console.WriteLine($"Id:{pr.Id}, Name:{pr.Name}");
Still good.
Now, let's make a small change to our immutable class by renaming a constructor parameter:
class SomeImmutablePoco
{
public SomeImmutablePoco(int pocoId, string name)
{
Id = pocoId;
Name = name;
}
public int Id{get;}
public string Name{get;}
}
then:
var p = new SomeImmutablePoco(666, "diabolo");
var json = JsonConvert.SerializeObject(p);
var pr = JsonConvert.DeserializeObject<SomeImmutablePoco>(json);
Console.WriteLine($"Id:{pr.Id}, Name:{pr.Name}");
Oh dear... It looks like Json.NET is doing some reflective magic over the names of our constructor parameters and matching them to property names in our POCO/json. This means that our freshly deserialized object doesn't get an Id assigned to it. When we print out the Id, it's 0.
This is bad, and particularly troublesome to track down.
This problem might exist in a large collection of POCOs. How can I automate finding these problem POCO classes?
Here is the code that finds such classes using reflection:
var types = new List<Type>() { typeof(SomeImmutablePoco) }; // get all types using reflection
foreach (var type in types)
{
var props = type.GetProperties(bindingAttr: System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance);
foreach (var ctor in type.GetConstructors())
{
foreach (var param in ctor.GetParameters())
{
if (!props.Select(prop => prop.Name.ToLower()).Contains(param.Name.ToLower()))
{
Console.WriteLine($"The type {type.FullName} may have problems with Deserialization");
}
}
}
}
You can map your json property like that:
class SomeImmutablePoco
{
public SomeImmutablePoco(int pocoId, string name)
{
Id = pocoId;
Name = name;
}
[JsonProperty("pocoId")]
public int Id { get; }
public string Name { get; }
}

Reflection - object comparison & default values

I'm trying to compare two complex objects in C#, and produce a Dictionary containing the differences between the two.
If I have a class like so:
public class Product
{
public int Id {get; set;}
public bool IsWhatever {get; set;}
public string Something {get; set;}
public int SomeOtherId {get; set;}
}
And one instance, thus:
var p = new Product
{
Id = 1,
IsWhatever = false,
Something = "Pony",
SomeOtherId = 5
};
and another:
var newP = new Product
{
Id = 1,
IsWhatever = true
};
To get the differences between these, i'm doing stuff that includes this:
var oldProps = p.GetType().GetProperties();
var newProps = newP.GetType().GetProperties();
// snip
foreach(var newInfo in newProps)
{
var oldVal = oldInfo.GetValue(oldVersion, null);
var newVal = newInfo.GetValue(newVersion,null);
}
// snip - some ifs & thens & other stuff
and it's this line that's of interest
var newVal = newInfo.GetValue(newVersion,null);
Using the example objects above, this line would give me a default value of 0 for SomeOtherId (same story for bools & DateTimes & whathaveyou).
What i'm looking for is a way to have newProps include only the properties that are explicitly specified in the object, so in the above example, Id and IsWhatever. I've played about with BindingFlags to no avail.
Is this possible? Is there a cleaner/better way to do it, or a tool that's out there to save me the trouble?
Thanks.
There is no flag to tell if you a property was explicitly set. What you could do is declare your properties as nullable types and compare value to null.
If i understand you correctly, this is what microsoft did with the xml wrapping classes, generated with the xsd utility, where you had a XIsSpecified, or something like that, for each property X.
So this is what You can do as well - instead of public int ID{get;set;}, add a private member _id , or whatever you choose to call it, and a boolean property IDSpecified which will be set to true whenever Id's setter is called
I ended up fixing the issue without using reflection (or, not using it in this way at least).
It goes, more or less, like this:
public class Comparable
{
private IDictionary<string, object> _cache;
public Comparable()
{
_cache = new Dictionary<string, object>();
}
public IDictionary<string, object> Cache { get { return _cache; } }
protected void Add(string name, object val)
{
_cache.Add(name, val);
}
}
And the product implementation goes to this:
public class Product : Comparable
{
private int _id;
private bool _isWhatever;
private string _something;
private int _someOtherId;
public int Id {get { return _id; } set{ _id = value; Add("Id", value); } }
public bool IsWhatever { get { return _isWhatever; } set{ _isWhatever = value; Add("IsWhatever ", value); } }
public string Something {get { return _something; } set{ _something = value; Add("Something ", value); } }
public int SomeOtherId {get { return _someOtherId; } set{ _someOtherId = value; Add("SomeOtherId", value); } }
}
And the comparison is then pretty straightforward
var dic = new Dictionary<string, object>();
foreach(var obj in version1.Cache)
{
foreach(var newObj in version2.Cache)
{
//snip -- do stuff to check equality
dic.Add(....);
}
}
Doesn't hugely dirty the model, and works nicely.

Storing/restoring values from a class to/from a list of property names and values

I am not sure what the best and simplest way to do this, so any advice is appreciated.
I want to get all the fields on any/all/single domain entity class and add prefix/remove prefix dynamically when calling a particular method.
For example, I have entities such as:
public class Shop
{
public string TypeOfShop{get;set}
public string OwnerName {get;set}
public string Address {get;set}
}
public class Garage
{
public string Company {get;set}
public string Name {get;set}
public string Address {get;set}
}
and so on...
I want to get a list of the properties with a prefix:
public Class Simple
{
public class Prop
{
public string Name{get;set;}
public string Value{get;set;}
}
public ICollection list = new List<Prop>();
//set all prop
public void GetPropertiesWithPrefix(Garage mygarage, string prefix)
{
list.Add(new Prop{Name = prefix + "_Company", Value = mygarage.Company});
//so on... upto 50 props...
}
}
//to get this list I can simple call the list property on the Simple class
When reading each field I am using a switch statement and setting the value.
//Note I return a collection of Prop that have new values set within the view,lets say
//this is a result returned from a controller with the existing prop names and new values...
public MyGarage SetValuesForGarage(MyGarage mygarage, string prefix, ICollection<Prop> _props)
{
foreach (var item in _prop)
{
switch(item.Name)
{
case prefix + "Company":
mygarage.Company = item.Value;
break;
//so on for each property...
}
}
}
Is there a better, simpler or more elegant way to do this with linq or otherwise?
You could store props in a dictionary, then have:
mygarage.Company = _props[prefix + "_Company"];
mygarage.Address = _props[prefix + "_Address"];
//And so on...
in your SetValuesForGarage method instead of a loop with a switch inside.
EDIT
For more info on using Dictionary see MSDN.
You can define list something like:
Dictionary<string, string> list = new Dictionary<string, string>();
And have something like the following in your GetPropertiesWithPrefix method:
list.Add(prefix + "_Company", mygarage.Company);
list.Add(prefix + "_Address", mygarage.Address);
//And so on...
This would eliminate your Prop class.
Maybe the following method works for you. It takes any object, looks up its properties and returns a list with your Prop objects, each for every property.
public class PropertyReader
{
public static List<Prop> GetPropertiesWithPrefix(object obj, string prefix)
{
if (obj == null)
{
return new List<Prop>();
}
var allProps = from propInfo
in obj.GetType().GetProperties()
select new Prop()
{
Name = prefix + propInfo.Name,
Value = propInfo.GetValue(obj, null) as string
};
return allProps.ToList();
}
}

Enumerate with return type other than string?

Since enumeration uses integers, what other structure can I use to give me enum-like access to the value linked to the name:
[I know this is wrong, looking for alternative]
private enum Project
{
Cleanup = new Guid("2ED3164-BB48-499B-86C4-A2B1114BF1"),
Maintenance = new Guid("39D31D4-28EC-4832-827B-A11129EB2"),
Upgrade = new Guid("892F865-E38D-46D7-809A-49510111C1"),
Sales = new Guid("A5690E7-1111-4AFB-B44D-1DF3AD66D435"),
Replacement = new Guid("11E5CBA2-EDDE-4ECA-BDFD-63BDBA725C8C"),
Modem = new Guid("6F686C73-504B-111-9A0B-850C26FDB25F"),
Audit = new Guid("30558C7-66D9-4189-9BD9-2B87D11190"),
Queries = new Guid("9985242-516A-4151-B7DD-851112F562")
}
EDIT 2014-07-20
This is a newer answer to this question. Using the Attribute class with a helper method, define the extra attributes needed on your enum.
public enum MultiValueEnum
{
[FooAttribute("alpha", 20d, true)]
First,
[FooAttribute("beta", 40.91d, false)]
Second,
[FooAttribute("gamma", 1.2d, false)]
Third,
}
public class FooAttribute : Attribute
{
internal FooAttribute(string name, double percentage, bool isGood)
{
this.Name = name;
this.Percentage = (decimal)percentage;
this.IsGood = isGood;
}
public string Name { get; private set; }
public decimal Percentage { get; private set; }
public bool IsGood { get; private set; }
}
public static TAttribute GetAttribute<TAttribute>(this Enum value)
where TAttribute : Attribute
{
var type = value.GetType();
var name = Enum.GetName(type, value);
return type.GetField(name)
.GetCustomAttributes(false)
.OfType<TAttribute>()
.SingleOrDefault();
}
Which makes it this easy:
MultiValueEnum enumVar = MultiValueEnum.First;
var enumStringValue = enumVar.GetAttribute<FooAttribute>().Name;
var enumValueDecimal = enumVar.GetAttribute<FooAttribute>().Percentage;
var enumBool = enumVar.GetAttribute<FooAttribute>().IsGood;
Otherwise you could create a custom Attribute for your enum, which can hold the Guid.
Something alongside these lines:
class EnumGuid : Attribute
{
public Guid Guid;
public EnumGuid(string guid)
{
Guid = new Guid(guid);
}
}
And you'd then use it like so:
enum Project
{
[EnumGuid("2ED3164-BB48-499B-86C4-A2B1114BF1")]
Cleanup = 1,
[EnumGuid("39D31D4-28EC-4832-827B-A11129EB2")]
Maintenance = 2
// and so forth, notice the integer value isn't supposed to be used,
// it's merely there because not assigning any value is a performance overhead.
}
And finally you could (I always do this) create an extension for easily getting the guid:
static Guid GetEnumGuid(this Enum e)
{
Type type = e.GetType();
MemberInfo[] memInfo = type.GetMember(e.ToString());
if (memInfo != null && memInfo.Length > 0)
{
object[] attrs = memInfo[0].GetCustomAttributes(typeof(EnumGuid),false);
if (attrs != null && attrs.Length > 0)
return ((EnumGuid)attrs[0]).Guid;
}
throw new ArgumentException("Enum " + e.ToString() + " has no EnumGuid defined!");
}
So in the end all you have to with your enums is:
Guid guid = Project.Cleanup.GetEnumGuid();
I use this approach to attach descriptions to enums, typically longer strings containing spaces, which thus cannot be used as names.
I've seen this method (struct) used by SubSonic to store Column and Table names.
internal struct Project
{
public static Guid Cleanup = new Guid("2ED3164-BB48-499B-86C4-A2B1114BF1");
public static Guid Maintenance = new Guid("39D31D4-28EC-4832-827B-A129EB2");
public static Guid Upgrade = new Guid("892F865-E38D-46D7-809A-49510111C1");
public static Guid Sales = new Guid("A5690E7-1111-4AFB-B44D-1DF3AD66D435");
public static Guid Replacement = new Guid("11E5CBA2-EDDE-4ECA-BD63-B725C8C");
public static Guid Modem = new Guid("6F686C73-504B-111-9A0B-850C26FDB25F");
public static Guid Audit = new Guid("30558C7-66D9-4189-9BD9-2B87D11190");
public static Guid Queries = new Guid("9985242-516A-4151-B7DD-851112F562");
}
EDIT:- Thanks for commenting on deficiencies in code. In first place it will compile if the Guid strings are not invalid. As for not create instances to access variables yes they need to be public static
I would probably go the dictionary route on this one. Have a lookup table basically:
public class GuidMapper
{
private Dictionary<GuidTypes, Guid> mGuidMap = new Dictionary<GuidTypes, Guid>();
public enum GuidTypes: int
{
Cleanup,
Maintenance,
Upgrade,
Sales,
Replacement,
Modem,
Audit,
Queries
}
public GuidMapper()
{
mGuidMap.Add(GuidTypes.Cleanup, new Guid("2ED31640-BB48-499B-86C4-A2B1114BF100"));
mGuidMap.Add(GuidTypes.Maintenance, new Guid("39D31D40-28EC-4832-827B-A11129EB2000"));
mGuidMap.Add(GuidTypes.Upgrade, new Guid("892F8650-E38D-46D7-809A-49510111C100"));
mGuidMap.Add(GuidTypes.Sales, new Guid("A5690E70-1111-4AFB-B44D-1DF3AD66D435"));
mGuidMap.Add(GuidTypes.Replacement, new Guid("11E5CBA2-EDDE-4ECA-BDFD-63BDBA725C8C"));
mGuidMap.Add(GuidTypes.Modem, new Guid("6F686C73-504B-1110-9A0B-850C26FDB25F"));
mGuidMap.Add(GuidTypes.Audit, new Guid("30558C70-66D9-4189-9BD9-2B87D1119000"));
mGuidMap.Add(GuidTypes.Queries, new Guid("99852420-516A-4151-B7DD-851112F56200"));
}
public Guid GetGuid(GuidTypes guidType)
{
if (mGuidMap.ContainsKey(guidType))
{
return mGuidMap[guidType];
}
return Guid.Empty;
}
}
If you need proper enum-like semantics and type-safety then you can use a pattern like this.
(You could flesh it out further if you require extras like conversion operators, GetUnderlyingType, ToString etc. If you wanted to re-use the pattern for multiple enum-like classes with different underlying types then you could move any common code into a generic, abstract base class.)
Project x = Project.Cleanup;
Project y = Project.Cleanup;
Project z = Project.Maintenance;
Console.WriteLine(x == y); // True
Console.WriteLine(x == z); // False
Console.WriteLine(x.Value); // 47801daa-7437-4bfe-a240-9f7c583018a4
// this line will cause a compiler error
Console.WriteLine(x == new Guid("47801daa-7437-4bfe-a240-9f7c583018a4"));
// ...
public class Project
{
private Project(Guid v) { Value = v; }
public Guid Value { get; private set; }
public static readonly Project Cleanup =
new Project(new Guid("47801daa-7437-4bfe-a240-9f7c583018a4"));
public static readonly Project Maintenence =
new Project(new Guid("2548a7f3-7bf4-4533-a6c1-dcbcfcdc26a5"));
public static readonly Project Upgrade =
new Project(new Guid("ed3c3e73-8e6a-4c09-84ae-7f0876d194aa"));
}
When confronted with this kind of problem I used structs with consts as public members:
public struct FileExtensions
{
public const string ProcessingExtension = ".lck";
public const string ProcessedExtension = ".xml";
public const string FailedExtension = ".failed";
public const string CsvExtension = ".csv";
}
You could create a static class that just contains constant values.
For example:
internal static class Project
{
public static readonly Guid Cleanup = new Guid("2ED3164-BB48-499B-86C4-A2B1114BF1");
public static readonly Guid Maintenance = new Guid("39D31D4-28EC-4832-827B-A11129EB2");
public static readonly Guid Upgrade = new Guid("892F865-E38D-46D7-809A-49510111C1");
}
This way the class acts simply as a container and object cannot be created from it.
In VB this would be a Module:
Friend Module Project
Public Shared ReadOnly Cleanup As Guid = New Guid("2ED3164-BB48-499B-86C4-A2B1114BF1")
Public Shared ReadOnly Maintenance As Guid = New Guid("39D31D4-28EC-4832-827B-A11129EB2")
Public Shared ReadOnly Upgrade As Guid = New Guid("892F865-E38D-46D7-809A-49510111C1")
End Module
The enum type can only support the integral types (except char) as its value. You could however use something like a Dictionary to do lookups of a a name to a value.
Dictionary<Guid> lookup = new Dictionary<Guid>();
lookup["Cleanup"] = new Guid("2ED3164-BB48-499B-86C4-A2B1114BF1");
lookup["Maintenance"] = new Guid("39D31D4-28EC-4832-827B-A11129EB2");
lookup["Upgrade"] = new Guid("892F865-E38D-46D7-809A-49510111C1");
// etc...
Another alternative is to have a series of readonly values in a static class.
public static class Guids
{
public static readonly Guid Cleanup = new Guid("2ED3164-BB48-499B-86C4-A2B1114BF1");
public static readonly Guid Maintenance = new Guid("39D31D4-28EC-4832-827B-A11129EB2");
public static readonly Guid Upgrade = new Guid("892F865-E38D-46D7-809A-49510111C1");
}

Categories