A generic enum as passed parameter - c#

Say I want to create a method that accepts enum instead of a string so I could specify a parameter instead of writing string value representing the passed parameter.
For instance, let's say mods are strings of names so each of the variants has items of it's own and do has to place a call to chosen item.
public void DoWithMode(chosenMod parModifier)
{
string SelectedM = parModifier.ToString();
dedicateLineTo(Seleted...) or something
}
public class Com
{
public enum chosenMode{dummy1, dummy2};
}
public class Tel:Com
{
public new emum chosenMode {Telmod1, Telmod2};
public Tel
{
DoWithMode(chosenMode.Tel1mode);
}
}
class fax:Com
{
emum new chosenMode {Faxmod1, Faxmod2};
public fax
{
DoWithMode(chosenMode.Faxmod2);
}
}
What if I would like to make a generic ChosenMode. Say, for example, phone and fax have some common usage with the Do() method, i could make some overrides but this is only 2 kinds what if I have 20 or more classes and each has its own items to pass?
So it's only strings or method overrides though I was thinking of the comfortable usage of enum rather a class of const strings.
What is the workaround for this case?
I could do something else using enum type but then intellisense would not auto-suggest it so i would need to write something like
DoSomething(namespaceA.classT.subclassV.classX....class.modifier.item)

Related

Constrain a string parameter to be a constant from a specific class

This is probably an incredibly dumb question but: I have a function that takes in a string, and I want to make sure that the string is a constant from a specific class. Essentially the effect I'm looking for is what enums do:
enum MyEnum {...}
void doStuff(MyEnum constValue) {...}
Except with strings:
static class MyFakeStringEnum {
public const string Value1 = "value1";
public const string Value2 = "value2";
}
// Ideally:
void doStuff(MyFakeStringEnum constValue) {...}
// Reality:
void doStuff(string constValue) {...}
I know this can technically be achieved by doing some thing like
public static class MyFakeStringEnum {
public struct StringEnumValue {
public string Value { get; private set; }
public StringEnumValue(string v) { Value = v; }
}
public static readonly StringEnumValue Value1 = new StringEnumValue("value1");
public static readonly StringEnumValue Value2 = new StringEnumValue("value2");
}
void doStuff(MyFakeStringEnum.StringEnumValue constValue) {...}
But it feels kind of overkill to make an object for just storing one single value.
Is this something doable without the extra code layer and overhead?
Edit: While a enum can indeed be used for a string, I'd like to avoid it for several reasons:
The string values may not always be a 1:1 translation from the enum. If I have a space in there, different capitalization, a different character set/language, etc. I'd have to transform the enum in every function where I want to use it. It might not be a lot of overhead or a performance hit in any way, but it still should be avoided--especially when it means that I'm always mutating something that should be constant.
Even if I use a separate string array map to solve the above function, I would still have to access the translations instead of just being able to use the enum directly. A map would also mean having two sources for the same data.
I'm interested in this concept for different data types, ex. floats, ulongs, etc. that cannot be easily represented by enum names or stored as an enum value.
As for string -> enum, the point of using an enum in the first place for me is that I can rely on intellisense to give me a constant that exists; I don't want to wait until compile time or runtime to find out. Passing in an actual string would be duck typing and that's something I definitely don't want to do in a strongly typed language.
I would suggest you create an enum and parse the string value into an enum member.
You can use the Enum.Parse method to do that. It throws ArgumentException if the provided value is not a valid member.
using System;
class Program
{
enum MyEnum
{
FirstValue,
SecondValue,
ThirdValue,
FourthValue
}
public static void doStuff(string constValue)
{
var parsedValue = Enum.Parse(typeof(MyEnum), constValue);
Console.WriteLine($"Type: { parsedValue.GetType() }, value: { parsedValue }");
}
static void Main(string[] args)
{
doStuff("FirstValue"); // Runs
doStuff("FirstValuesss"); // Throws ArgumentException
}
}

Factory pattern with a class that can has different class sub types

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
}

Inheriting from a class and adding an additional property

I have a class in one application - that I cannot change (legacy) - that is inside of a assembly (DLL file):
public class ShippingMethod
{
public string ShipMethodCode { get; set; }
public string ShipMethodName { get; set; }
public decimal ShippingCost { get; set; }
public List<ShippingMethod> GetAllShippingMethods()
{
......
}
}
I have a second application that is referencing that assembly (DLL file) and needs to populate a drop-down with all the Shipping Methods. Ex: "UPS - $3.25"
The issue is that it needs to be using the correct format for different currencies. Ex: $3.25 or 3.25€ depending on a parameter called CountryID.
I have written a function String DisplayMoney(Decimal Amount, Integer CountryID) that will return the correct format of the amount.
Now I need to apply this function to every shipping method and save it into a new list.
What is the best way to do this?
I can create another class called LocalizedShippingMethods as follows:
public class LocalizedShippingMethod
{
public ShippingMethod ShipMethod { get; set; }
public string LocalizedShippingCost { get; set; }
}
Is this the best way to accomplish this? Is there a better way to do this using inheritance? And if I use inheritance, how do I get the values from the first LIST into the NEW LIST?
That is indeed a good method of doing it. You can use a pretty quick Linq query to pull the old List into the new one:
List<LocalizedShippingMethod> Translate(List<ShippingMethod> oldList)
{
return oldList.Select(a => new LocalizedShippingMethod
{
// Initialize properties according to however you translate them
}).ToList();
}
Additionally, to make this more streamlined and obvious, you could do any of the following to aid in the translation:
Create a constructor for LocalizedShippingMethod that takes in a ShippingMethod and properly sets the properties
Create a static method on LocalizedShippingMethod that takes in a ShippingMethod and returns an initialized LocalizedShippingMethod
Create an operator on LocalizedShippingMethod that converts from a ShippingMethod
Create an extension method on ShippingMethod, call it ToLocalized() that returns a LocalizedShippingMethod
What if you create an extension method for the ShippingMethod class?
The best way to do this is whatever way works best for you. If you're the person who's going to have to maintain this code, what will make your life the easiest down the road?
Once you've answered that question, that is the best solution.

Extract value from Object?

I wanted to make a dynamic method in which i pass any instance of object i made, for example:
public class Employee()
{
public string FName;
public string SName;
.....etc.
}
The method i want is like the following:
public void methodName(Object oObject)
{
//lets say that i have passed object employee to it.
}
Is it possible to extract any values from the oObject, i have tried to do so but it have no attributes to do so, and when i put in the watch i can acutally see all the attribute of class employee in it.
So is there any way ?
There are many ways.
Update: you say you want the whole object. Casting or interfaces to expose the properties is the way foward.
You can cast the object to the specific type:
if (oObject is Employee)
{
string name = (oObject as Employee).FName;
}
You can expose an interface that defines what the method expects, then provided types implement the interface:
public interface IFirstName
{
string FName { get; }
}
public void methodName(IFirstName objectWithFirstName)
{
string name = objectWithFirstName.FName;
}
You can use dynamic and hope for the best at runtime (.NET 4):
public void methodName(dynamic oObject)
{
string name = oObject.FName;
}
And then there is reflection.
But the better question to ask is, is this a good method? I would be a little skeptical about methods that take anything and make expectations about things... though that's not to say it doesn't or shouldn't happen.
Yes, you can access values by simply type casting object back into Employee class like this
public void methodName(Object oObject)
{
//lets say that i have passed object employee to it.
//if oObject belongs to Employee class
if(oObject is Employee)
{
Employee employee = oObject as Employee;
//you can get access values here
}
}

C# Attributes - Arrays or Duplicates?

I am creating a network chat client in C# as a side project. In addition to simple text messages, I also have slash-prefixed commands that can be entered into the input TextBox. I used a modular approach by creating an enum that contains all the various commands, and then decorating those commands with attributes.
The attributes specify what slash-prefixed command can be entered to trigger the command, as well as any aliases to the primary command identifier and the command's usage.
Example:
public enum CommandType : byte
{
[PrimaryIdentifier("file"),
AdditionalIdentifier("f"),
CommandUsage("[<recipient>] [<filelocation>]")]
FileTransferInitiation,
[PrimaryIdentifier("accept"),
AdditionalIdentifier("a")]
AcceptFileTransfer,
// ...
}
My problem arises when I try to allow multiple aliases to the primary command. I have attempted this two ways: by allowing duplicates of the AdditionalIdentifier attribute, or by making the constructor argument in AdditionalIdentifier a params string[].
With the former, I implemented it by decorating the attribute class with AttributeUsage and setting AllowMultiple to true. While this does indeed achieve what I'm looking for, I'm feeling like it could get really noisy really fast to have several lines of aliases, in addition to the other attributes.
The latter also works, however, it generates the compiler warning CS3016, and says that that approach is not CLS-compliant. Obviously, this doesn't necessarily stop me from still using it, but I've learned to always treat warnings as errors.
My actual question is should I ignore my objections with duplicates and just go ahead and use them, or is there some other solution that could be used?
Thank you.
You could also use "params string[] aliases" in the constructor to allow a variable argument list:
[AttributeUsage(AttributeTargets.Method)]
class TestAttribute : Attribute
{
public TestAttribute(params string[] aliases)
{
allowedAliases = aliases;
}
public string[] allowedAliases { get; set; }
}
This would allow you to do:
[Test("test1", "test2", "test3")]
static void Main(string[] args)
Personally I would go with the AllowMultiple approach: I don't think the "noise" is going to be that much of a problem unless you really have truckloads of identifiers for each command. But if you don't like that and want to stay CLS-compliant, one other solution would be to provide overloaded constructors for AdditionalIdentifierAttribute:
public AdditionalIdentifierAttribute(string id) { ... }
public AdditionalIdentifierAttribute(string id1, string id2) { ... }
public AdditionalIdentifierAttribute(string id1, string id2, string id3) { ... }
The downside is that this does limit you to a predetermined number of identifiers.
That said, CLS compliance is really only a major consideration if you are building a library that others are likely to use (and specifically from other languages). If this type or the library is internal to your application, then it's reasonable to ignore CLS compliance warnings.
EDIT: Thinking further about this, you have quite a lot of attributes on those enums. You might want to consider creating an abstract Command class instead, and exposing the identifiers, usage, etc. as properties of that class; then derive concrete types of Command which return the appropriate values from those properties. This potentially also allows you to move the handling logic into those Command objects rather than switching on the enum value.
Why not have a single attribute with multiple properties? Have the property for the alias take a comma-separated list. This is the approach they take in MVC for things like the AuthorizeAttribute for Roles. Internally, the property parses the string into an array for ease of use in the attribute class, but it allows you an easy way to set up your configuration.
public class IdentifierAttribute
{
public string Name { get; set; }
public string Usage { get; set; }
private string[] aliasArray;
private string aliases;
public string Aliases
{
get { return this.aliases; }
set
{
this.aliases = value;
this.aliasArray = value.Split(',').Trim();
}
}
}
Then use it like:
public enum CommandType : byte
{
[Identifer( Name = "file", Aliases = "f", Usage = "..." )]
FileTransferType,
...
}
Yet another approach would be to have the attribute take an array of strings as a constructor parameter - that way, you get the compiler to parse the array for you (at the expense of a little more goop when applying the attribute) thus:
[Identifiers(new string[] {"Bill", "Ben", "Ted"})]
A quick 'n dirty example of implementing & using such a technique looks like this:
using System;
using System.Collections.ObjectModel;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
SomeClass.TellMeAboutYourself();
}
}
public class Identifiers : Attribute
{
private string[] names;
public Identifiers(string[] someNames)
{
names = someNames;
}
public ReadOnlyCollection<string> Names { get { return new ReadOnlyCollection<string>(names); } }
}
[Identifiers(new string[] {"Bill", "Ben", "Ted"})]
static class SomeClass
{
public static void TellMeAboutYourself()
{
Identifiers theAttribute = (Identifiers)Attribute.GetCustomAttribute(typeof(SomeClass), typeof(Identifiers));
foreach (var s in theAttribute.Names)
{
Console.WriteLine(s);
}
}
}
}

Categories