Calling Static Derived Class Method from Static Base Class Method - c#

Problem: I have an entity class (base class), from which I inherit multiple times. Now I have an Add-method and a Validate-method in all of my derived classes. These functions are identical in all derived class and they are static.
Here is my Add-method
public static long Add(DBData[] UserData)
{
SortedDictionary<string, DBData> Data = new SortedDictionary<string, DBData>();
foreach (DBData d in UserData)
{
Data.Add(d.FieldName, d);
}
if (Project.Validate(Data, OperationMode.Add))
{
return DBUtility.Insert("Project", VSCommon.Serialise(Data));
}
else
{
return -1;
}
}
Now where I have "Project" in above function (2 places, one if object of type Project this function belong too, and other is the database table name). These are the only differences in all my derived classes. I want to put this Add-method in my base class, so I can skip writing it multiple times in every derived class.
I search and found that some try to use generics but I didn't seem to pick it up as when I use generic declaration. When I call the Validate-method a compilation error came by. Also, I need the name of the class as string to get relevant table name.
Not sure I am able to define my problem, any help is appreciated. Thanks.

You could add a (abstract in base class & virtual) method that returns "Project" for this class and some other string for the other classes. Then just reference that from the static Add method.
I think you could also use reflecion to get the "Project" string, if needed. However I'd advise against doing this, because it adds unnecessary coupling between your database and your code.

I solve my issue using following change in ADD Function
public static long Add<T>(DBData[] UserData)
{
SortedDictionary<string, DBData> Data = new SortedDictionary<string, DBData>();
foreach (DBData d in UserData)
{
Data.Add(d.FieldName, d);
}
MethodInfo m = typeof(T).GetMethod("Validate");
bool r = (bool)m.Invoke(null, new object[] { Data, OperationMode.Add });
if (r)
{
return DBUtility.Insert(typeof(T).Name, VSCommon.Serialise(Data));
}
else
{
return -1;
}
}
And then I have to change my call to Project.Add<Project>(...); or Client.Add<Client>(...); instead of Project.Add(...) before. But that save lot of trouble for me finally :).
EDIT: I just realize that Project.Add<Client>(...) can also be called and this will insert into Client object. This is not good, so my problem is not actually solved :(.

Related

Explicitly cast base class to derived class

Problem: I have 2 types which are result sets of 2 different procedures in DB:
Proc1Result, Proc2Result (We had to split them - but they are basically the same as comes for input/output)
I then decided that I could make use of an interface to switch between needed procedures on runtime - but this means I would need 1 common type to which i could convert Proc1Result and Proc2Result
Just so I do not need to maintain this new class (create all the properties, add/remove if anything changes in DB result) - I derived this class from one of the results:
public class DerivedClassForInterface : Proc1Result {}
Then I implemented explicit cast from the 2nd proc which works fine, but when I want to implement explicit cast from base class to derived class - it wont allow me (since it kinda already "does" - but it fails at runtime):
public class DerivedClassForInterface : Proc1Result
{
//ok - and works as expected
public static explicit operator DerivedClassForInterface(Proc2Result v)
{
return new DerivedClassForInterface
{
...
};
}
//fail: 'user-defined' conversations to or from a base class are not allowed
public static explicit operator DerivedClassForInterface(Proc1Result v)
{
return new DerivedClassForInterface
{
...
};
}
}
so this works:
//result2 is of type Proc1Result
DerivedClassForInterface castedResult = (DerivedClassForInterface)result2;
//compiles - works as expected at runtime
but this does not:
//result1 is of type Proc1Result
DerivedClassForInterface castedResult = (DerivedClassForInterface)result1;
//compiles - conversation fails at runtime
So why I can not write my own explicit operator if you can not cast from base class to derived class?
Interesting that compiler allows me to cast from base to derived class, and yet it does not work at runtime.
Probably I will go just for simple functions which will do the "casting" for me. Anyone can suggest a better solution (keep in mind that I would like to keep "DerivedClassForInterface" to obey changes in "Proc1Result" (or "Proc2Result" - doesn't matter))
EDIT
#Peter Duniho - Here the types "Proc1Result" and "Proc2Result" are generated as results from stored procedures (linq2sql). I would like to have a code which I wont need to touch when output of those procedures change (since there are bunch of procedures we need to segment - and implementing new modules could and often does add more output).
Proc1 and Proc2 are basically same stored procedures (they require exactly the same input and provides same output (type-wise not data-wise)). Both of them work with different segments of data and are required to be separate.
Sorry for making this confusing (was at end of my working day...) and not clarifying - the question here actually is:
Why compiler lets me cast from base to derived class when runtime causes exception? And why I can not implement this casting myself (... because it kinda already does - but it just does not work at runtime?)
So from where I stand - it looks the following:
- I can not implement this cast because it already exists
- Yet it is doomed to not work
Here is "Minimal, Complete, and Verifiable code example" (thanks for the link):
//results from stored procedures in database which got splitted appart (linq 2 sql)
class Proc1Result { }
class Proc2Result { }
//
class DerivedClassForInterface : Proc1Result
{
public static explicit operator DerivedClassForInterface(Proc2Result v)
{
//this part would be exported in generic function
var derivedClassInstance = new DerivedClassForInterface();
var properties = v.GetType().GetProperties();
foreach (var property in properties)
{
var propToSet = derivedClassInstance.GetType().GetProperty(property.Name);
if (propToSet.SetMethod != null) propToSet.SetValue(derivedClassInstance, property.GetValue(v));
}
return derivedClassInstance;
}
}
interface IProcLauncher
{
DerivedClassForInterface GetNeededData();
}
class ProcLauncher1 : IProcLauncher
{
public DerivedClassForInterface GetNeededData()
{
var dataFromDb = new Proc1Result();/*just ilustrative*/
return (DerivedClassForInterface)dataFromDb;
}
}
class ProcLauncher2 : IProcLauncher
{
public DerivedClassForInterface GetNeededData()
{
var dataFromDb = new Proc2Result();/*just ilustrative*/
return (DerivedClassForInterface)dataFromDb;
}
}
class Program
{
static void Main(string[] args)
{
bool causeInvalidCastException = true;
IProcLauncher procedureLauncher;
if (causeInvalidCastException) procedureLauncher = new ProcLauncher1();
else procedureLauncher = new ProcLauncher2();
var result = procedureLauncher.GetNeededData();
Console.WriteLine("I got here!");
}
}
The idea was:
- Not have to change any code if output of procedures change.
- Decide at runtime which proc to use.
- Export the convertation part as generic function.
- Got to be injectable.
I can solve this - let say - by just 1 generic function which will handle conversation for all cases, but the question is above in bold.
I implemented the converting the following way:
class BaseConverter
{
protected T Convert<T, X>(X result)
{
var derivedClassInstance = Activator.CreateInstance<T>();
var derivedType = derivedClassInstance.GetType();
var properties = result.GetType().GetProperties();
foreach (var property in properties)
{
var propToSet = derivedType.GetProperty(property.Name);
if (propToSet.SetMethod != null)
{
propToSet.SetValue(derivedClassInstance, property.GetValue(result));
}
}
return derivedClassInstance;
}
protected List<T> Convert<T, X>(List<X> listResult)
{
var derivedList = new List<T>();
foreach (var r in listResult)
{
//can cope with this - since there will not ever be many iterations
derivedList.Add(Convert<T, X>(r));
}
return derivedList;
}
}
So interface implementation classes would inherit from it:
class ProcLauncher2 : BaseConverter, IProcLauncher
{
public DerivedClassForInterface GetNeededData()
{
var dataFromDb = new Proc2Result();/*just ilustrative*/
//usage (works for single result or list if I need a list returned):
return Convert<DerivedClassForInterface, Proc2Result>(dataFromDb);
}
//other methods...
}
Yet - it is not clear for me - why there is already cast from base class to derived - if that does not work. Imo - it should not be there and throw error at compile time.
I don't understand your question very well. You seem to say that the compiler lets you write the code you posted, but that it fails at runtime. This isn't my experience. I get a compile-time error on the explicit conversion operation for the base class:
error CS0553: 'Derived.explicit operator Derived(Base1)': user-defined conversions to or from a base class are not allowed
Seems pretty clear to me. As for why you aren't allowed to write code like that, you'd have to ask the language designers to know for sure, but it seems like a reasonable restriction to me. There already is a safe, built-in conversion from any base class to a derived class of that base class, as long as the base class instance is in fact an instance of the derived class. It would be confusing and likely to lead to bugs if programmers were allowed to make additional conversions, never mind greatly complicate the language specification's rules for the casting/conversion operator.
As for the broader problem, I don't understand the approach you've chosen. You're designing the classes exactly upside-down from the way one would normally do this. If you have a number of classes that all have shared members, you want to be able to treat all those classes as the same in some context, and you want to be able to implement those shared members exactly once and share them among the other classes, you would put all those members in a single base class, and then derive all your various types from that class.
I don't even see how your current approach addresses this concern:
Just so I do not need to maintain this new class (create all the properties, add/remove if anything changes in DB result)
Since Proc2Result doesn't inherit Proc1Result, if Proc1Result changes, you'll have to go change Proc2Result to match anyway. And any other similar types. And the DerivedClassForInterface class. And you have to change all the explicit operators. How is that better?
I would think you would prefer something like:
class BaseClassForInterface
{
// declare all shared members here
}
class Proc1Result : BaseClassForInterface { ... }
class Proc2Result : BaseClassForInterface { ... }
Then, for each new Proc...Result class, you simply inherit the base class, no need to re-write the members, and the conversion from each Proc...Result class is trivial. You don't even need to use the casting/conversion operator; the language already knows how to implicitly convert from derived classes to base classes, because the derived classes are the base classes.
This is, in fact, the standard way to use OOP. It's one of the most fundamental features of any OOP language.
If that doesn't get you back on track, you'll need to improve the question, so that it's more clear what you are doing and why. You'll also need to provide a good Minimal, Complete, and Verifiable code example that clearly illustrates your question, explaining precisely what that code does and what you want it to do instead.
Addendum:
Thanks for the edit. Your question is a lot more specific and clear now. I still have questions, but at least I understand the real context.
It seems to me that you already understand most of the basic answer to your question:
Why compiler lets me cast from base to derived class when runtime causes exception? And why I can not implement this casting myself (... because it kinda already does - but it just does not work at runtime?)
So from where I stand - it looks the following:
- I can not implement this cast because it already exists
- Yet it is doomed to not work
I.e. yes, I believe the language disallows this because there is already a built-in cast, and yes the exact approach you seek is doomed to not work.
As far as this part goes:
The idea was:
- Not have to change any code if output of procedures change.
- Decide at runtime which proc to use.
- Export the convertation part as generic function.
- Got to be injectable.
If I understand the first point, this is why you inherit one of the stored procedure types. So that you get the property declarations for free. Seems a little hacky to me, but I admit I do understand the motivation.
As I understand the third point above and your statement after in your post, you already know how you can write a generic method to do the conversion. E.g. something like:
DerivedClassForInterface ConvertToClassForInterface<T>(T t)
{
DerivedClassForInterface result = new DerivedClassForInterface();
Type resultType = typeof(DerivedClassForInterface);
PropertyInfo[] properties = typeof(T).GetProperties();
foreach (var property in properties)
{
var propToSet = resultType.GetProperty(property.Name);
if (propToSet.SetMethod != null)
{
propToSet.SetValue(result, property.GetValue(t));
}
}
return result;
}
I.e. essentially the code you show in your explicit operator (with some minor cleanup/optimization). Or maybe you aren't using the term "generic" literally, and just mean "general purpose". Obviously there's very little in the above that really benefits from the method being generic; you could just as easily use GetType() on the parameter, just as your explicit operator does.
Unfortunately, I don't know how the criteria "Got to be injectable" fits in here. Injectable, how? Do you mean you want to inject the code somewhere else? Or do you mean that the code needs to be compatible with an AOP system, or some other form of code injection applied to it?
Ignoring that part, which I don't understand, I would actually just leverage the compiler and runtime to do all the heavy lifting for me (including caching the reflection stuff, which in your code is going to be very slow). You could write a class like this:
class Wrapper
{
private dynamic _data;
public string Value { get { return _data.Value; } }
public Wrapper(dynamic data)
{
_data = data;
}
}
Given a couple of other classes like this:
class Result1
{
public string Value { get; set; }
}
class Result2
{
public string Value { get; set; }
}
Then you can use it like this:
Result1 r1 = new Result1 { Value = "result 1" };
Result2 r2 = new Result2 { Value = "result 2" };
Wrapper w1 = new Wrapper(r1), w2 = new Wrapper(r2);
Console.WriteLine("w1 result: " + w1.Value);
Console.WriteLine("w2 result: " + w2.Value);
I.e. just create an instance of Wrapper, passing the relevant object (in your case, this would be the generated type's from the stored procedure). The downside is, of course, that you do have to add properties to the Wrapper type to match your stored procedure. But I'm not convinced that's a bad thing. Even if you've somehow arranged it so that none of the rest of the code has to change, it's a relatively minor maintenance task.
And I suspect that altering the stored procedure requires changes elsewhere in the code anyway, to explicitly refer to the properties. Because after all, if the rest of the code is similarly completely agnostic regarding the specific class members (i.e. uses reflection all the way), then you could just pass the result objects around as object types, and not worry about the wrapper at all.

create an object depending on the caller object

I have many classes in a program but almost all of them have the same methods and call almost the same stored procedures in a SQL Server. The difference in the name is the name of the class ( "pa" + class + CRUD). Is there a way to create a common calling method?
I want to make a method that, called from, let's say, the Student class, would call "paStudentSelect" and return a Student object; and if the method is called from the Teacher class the called SP is "paTeacherSelect" and return a Teacher object.
Extra: I have to check for nulls that vary from class to class. Using a string array as a parameter would be possible to check the properties of the class named in the string array?
PS: I know the thing to do is refactor and think again the code, the tables and the SPs but it's not my program.
As you've described your class name, this should do it:
var proc_name = string.Format("pa{0}delete", GetType().Name);
Extra: yes. Using reflection you can get a PropertyDescriptor for the class named in the string array or, if you want, the Type array...
var types = new Type[] { typeof(Student), typeof(Teacher), ... };
foreach(var t types)
{
// todo: perform your null checks here
var proc_name = t.Name;
db.ExecuteSQLCommandOrWhatever(proc_name);
}
I don't see why you would want to do such a thing. You say that you want to be able to call a common method from different classes(Student, Teacher, etc). If you were calling the method from a common place it made more sense to create a common method but when you are actually calling the method from the classes themselves you might as well call the appropriate SP and avoid the pitfalls with the type of approach you should take(code breaks with name changes and possibly more).
If you absolutely have to do this I can think of two possible solutions:
1) Extension Methods: create a common abstact type(you probably have one already) for your classes and add an extension method for that abstract class. The method could be something like this:
protected void CallCRUD(this AbstractType obj)
{
//call SP on this.TableName
}
2) Generic Method: create a static generic method:
public static T CallCRUD<T>()
{
//call SP on typeof(T).Name
}
Your "Extra:" is very vague so I don't have an answer for you there.

How to refactor Switch into Dictionary/Factory

I am trying run a 'Recipe' read from a text file and parsed line by line to dynamically call a series of methods. I think I need to implement a Factory after doing quite a bit of googling, but I am lacking some key details. This is the closest example I have:
http://simpleprogrammer.com/2010/08/17/pulling-out-the-switch-its-time-for-a-whooping/
The following code is a snippet of what have now.
internal static void Run(int Thread_ID, List<StringBuilder> InstructionSet, List<double>[] Waveforms)
{
//Init
List<double>[] Register = new List<double>[10];
for (int i = 0; i < Waveforms.Length; i++) { Register[i] = new List<double>(Waveforms[i]); }
for (int i = 0; i < Register.Length; i++) { if (Register[i] == null) { Register[i] = new List<double>(); } }
//Run Recipe Steps
foreach (var item in InstructionSet)
{
Step Op = Step.Parse(item.ToString());
switch (Op.TaskName)
{
case "SimpleMovingAverage":
Register[Convert.ToInt32(Op.Args[0])] = Signal_Filters.SimpleMovingAverage(Register[Convert.ToInt32(Op.Args[1])], Convert.ToInt32(Op.Args[2]));
break;
case "RollingSteppedStdDeviation":
Register[Convert.ToInt32(Op.Args[0])] = Signal_Filters.RollingSteppedStdDeviation(Register[Convert.ToInt32(Op.Args[1])], Convert.ToInt32(Op.Args[2]), Convert.ToInt32(Op.Args[3]));
break;
//... etc. many, many methods to be called.
}
}
}
... and below is the portion of the example I have questions about:
public static class MoveFactory
{
private static Dictionary<string, Func<IMove>> moveMap = new Dictionary<string, Func<IMove>>()
{
{"Up", () => { return new UpMove(); }},
{"Down", () => { return new DownMove(); }},
{"Left", () => { return new LeftMove(); }}
// ...
};
public static IMove CreateMoveFromName(string name)
{
return moveMap[name]();
}
}
Can I generate the Dictionary list automatically? So that whenever I add a new class that implements my Factory Interface (my equivalent of IMove), I don't have to update my dictionary or pretty much any other part of my code. Perhaps this can forced as part of the Interface?
In the above example code, I don't see it passing arguments in and out. Looking at my code I have data I need to mutate progressively... How would I do this using a Factory.
The Factory needs to be thread-safe as I want to pass different initial data to multiple workers each running their own recipe.
Let's tackle these one at a time.
Building The Dictionary Dynamically
This is actually pretty easy to do using a combination of Reflection and Custom Attributes.
The creation of an Attribute is pretty trivial, so I'll leave that to you to look up, but let's assume you have one called MoveNameAttribute that can be applied at a class level. You can then decorate your classes that implement IMove like so:
[MoveName("Up")]
class UpMove: IMove{}
[MoveName("Down")]
class DownMove: IMove{}
Now you can use Reflection and a little LINQ to extract these class types into a dictionary, and create new instances of those types on demand using the key specified in your custom attribute.
While the entire Factory itself is pretty short in terms of lines of code, Reflection can be daunting if you have never done it before. I've annotated every line to explain what is going on.
internal static class MoveFactory
{
private static readonly IDictionary<String, Type> _moveTypes;
static MoveFactory()
{
_moveTypes = LoadAllMoveTypes();
}
private static IDictionary<string, Type> LoadAllMoveTypes()
{
var asm =
//Get all types in the current assembly
from type in Assembly.GetExecutingAssembly().GetTypes()
//Where the type is a class and implements "IMove"
where type.IsClass && type.GetInterface("IMove") != null
//Only select types that are decorated with our custom attribute
let attr = type.GetCustomAttribute<MoveNameAttribute>()
where attr != null
//Return both the Name and the System.Type
select new
{
name = attr.Name,
type
};
//Convert the results to a Dictionary with the Name as a key
// and the Type as the value
return asm.ToDictionary(move => move.name, move => move.type);
}
internal static IMove CreateMove(String name)
{
Type moveType;
//Check to see if we have an IMove with the specific key
if(_moveTypes.TryGetValue(name, out moveType))
{
//Use reflection to create a new instance of that IMove
return (IMove) Activator.CreateInstance(moveType);
}
throw new ArgumentException(
String.Format("Unable to locate move named: {0}", name));
}
}
Now that you have your factory, you can simply create new instances like this:
var upMove = MoveFactory.CreateMove("Up");
var downMove = MoveFactory.CreateMove("Down");
Since the factory uses a Static Constructor, it will only populate this list once, and will automatically pick up your new classes.
Passing Arguments
I'm not 100% sure what your use case is here, but it doesn't look like you need to pass arguments to your Factory, rather to some method on your IMove. However, you have a variable number of arguments that can be passed in.
If this is the case, then you are simply going to have to live with a bit of ugliness in your design. You need a very generic method on your IMove interface:
public interface IMove
{
double Compute(double val1, params int[] args);
}
Now your individual move classes are going to have to just be diligent and check to ensure that they get the proper number of parameters. I'll leave this as an exercise for you, but this should give you what you need based on the example above.
Thread Safety
As it stands the factory implementation above is thread safe because it doesn't rely on any shared state, and the underlying dictionary is essentially immutable. Each call to CreateMove returns a brand new IMove instance.
Now whether or not your implementations of IMove are thread safe is up to you :)
Whew! That was a long answer, but hopefully this will help you out.

ReSharper warns: "Static field in generic type"

public class EnumRouteConstraint<T> : IRouteConstraint
where T : struct
{
private static readonly Lazy<HashSet<string>> _enumNames; // <--
static EnumRouteConstraint()
{
if (!typeof(T).IsEnum)
{
throw new ArgumentException(
Resources.Error.EnumRouteConstraint.FormatWith(typeof(T).FullName));
}
string[] names = Enum.GetNames(typeof(T));
_enumNames = new Lazy<HashSet<string>>(() => new HashSet<string>
(
names.Select(name => name), StringComparer.InvariantCultureIgnoreCase
));
}
public bool Match(HttpContextBase httpContext, Route route,
string parameterName, RouteValueDictionary values,
RouteDirection routeDirection)
{
bool match = _enumNames.Value.Contains(values[parameterName].ToString());
return match;
}
}
Is this wrong? I would assume that this actually has a static readonly field for each of the possible EnumRouteConstraint<T> that I happen to instance.
It's fine to have a static field in a generic type, so long as you know that you'll really get one field per combination of type arguments. My guess is that R# is just warning you in case you weren't aware of that.
Here's an example of that:
using System;
public class Generic<T>
{
// Of course we wouldn't normally have public fields, but...
public static int Foo;
}
public class Test
{
public static void Main()
{
Generic<string>.Foo = 20;
Generic<object>.Foo = 10;
Console.WriteLine(Generic<string>.Foo); // 20
}
}
As you can see, Generic<string>.Foo is a different field from Generic<object>.Foo - they hold separate values.
From the JetBrains wiki:
In the vast majority of cases, having a static field in a generic type
is a sign of an error. The reason for this is that a static field in a
generic type will not be shared among instances of different close
constructed types. This means that for a generic class C<T> which
has a static field X, the values of C<int>.X and C<string>.X
have completely different, independent values.
In the rare cases when you do need the 'specialized' static fields,
feel free to suppress the warning.
If you need to have a static field shared between instances with
different generic arguments, define a non-generic base class to
store your static members, then set your generic type to inherit from
this type.
This is not necessarily an error - it is warning you about a potential misunderstanding of C# generics.
The easiest way to remember what generics do is the following:
Generics are "blueprints" for creating classes, much like classes are "blueprints" for creating objects. (Well, this is a simplification though. You may use method generics as well.)
From this point of view MyClassRecipe<T> is not a class -- it is a recipe, a blueprint, of what your class would look like. Once you substitute T with something concrete, say int, string, etc., you get a class. It is perfectly legal to have a static member (field, property, method) declared in your newly created class (as in any other class) and no sign of any error here.
It would be somewhat suspicious, at first sight, if you declare static MyStaticProperty<T> Property { get; set; } within your class blueprint, but this is legal too. Your property would be parameterized, or templated, as well.
No wonder in VB statics are called shared. In this case however, you should be aware that such "shared" members are only shared among instances of the same exact class, and not among the distinct classes produced by substituting <T> with something else.
There are several good answers here already, that explain the warning and the reason for it. Several of these state something like having a static field in a generic type generally a mistake.
I thought I'd add an example of how this feature can be useful, i.e. a case where suppressing the R#-warning makes sense.
Imagine you have a set of entity-classes that you want to serialize, say to Xml. You can create a serializer for this using new XmlSerializerFactory().CreateSerializer(typeof(SomeClass)), but then you will have to create a separate serializer for each type. Using generics, you can replace that with the following, which you can place in a generic class that entities can derive from:
new XmlSerializerFactory().CreateSerializer(typeof(T))
Since your probably don't want to generate a new serializer each time you need to serialize an instance of a particular type, you might add this:
public class SerializableEntity<T>
{
// ReSharper disable once StaticMemberInGenericType
private static XmlSerializer _typeSpecificSerializer;
private static XmlSerializer TypeSpecificSerializer
{
get
{
// Only create an instance the first time. In practice,
// that will mean once for each variation of T that is used,
// as each will cause a new class to be created.
if ((_typeSpecificSerializer == null))
{
_typeSpecificSerializer =
new XmlSerializerFactory().CreateSerializer(typeof(T));
}
return _typeSpecificSerializer;
}
}
public virtual string Serialize()
{
// .... prepare for serializing...
// Access _typeSpecificSerializer via the property,
// and call the Serialize method, which depends on
// the specific type T of "this":
TypeSpecificSerializer.Serialize(xmlWriter, this);
}
}
If this class was NOT generic, then each instance of the class would use the same _typeSpecificSerializer.
Since it IS generic however, a set of instances with the same type for T will share a single instance of _typeSpecificSerializer (which will have been created for that specific type), while instances with a different type for T will use different instances of _typeSpecificSerializer.
An example
Provided the two classes that extend SerializableEntity<T>:
// Note that T is MyFirstEntity
public class MyFirstEntity : SerializableEntity<MyFirstEntity>
{
public string SomeValue { get; set; }
}
// Note that T is OtherEntity
public class OtherEntity : SerializableEntity<OtherEntity >
{
public int OtherValue { get; set; }
}
... let's use them:
var firstInst = new MyFirstEntity{ SomeValue = "Foo" };
var secondInst = new MyFirstEntity{ SomeValue = "Bar" };
var thirdInst = new OtherEntity { OtherValue = 123 };
var fourthInst = new OtherEntity { OtherValue = 456 };
var xmlData1 = firstInst.Serialize();
var xmlData2 = secondInst.Serialize();
var xmlData3 = thirdInst.Serialize();
var xmlData4 = fourthInst.Serialize();
In this case, under the hood, firstInst and secondInst will be instances of the same class (namely SerializableEntity<MyFirstEntity>), and as such, they will share an instance of _typeSpecificSerializer.
thirdInst and fourthInst are instances of a different class (SerializableEntity<OtherEntity>), and so will share an instance of _typeSpecificSerializer that is different from the other two.
This means you get different serializer-instances for each of your entity types, while still keeping them static within the context of each actual type (i.e., shared among instances that are of a specific type).

How do I setup a nested/chained function within a C# Class

Here is what I'm trying to setup
My class is named Inventory
I have a static function named List_Departments()
I would like to be able to add an additional function to modify the previous
For Example: Inventory.List_Departments().ToHTML() would return an HTML formatted string containing the data from List_Departments()
If possible i'd like to reuse the same code for another function such as List_Categories()
I would really appreciate a nudge in the right direction on this. I just can't seem to find the correct terminology/ search term to pull up the info I need. Thank you very much for your help, and sorry for the somewhat stupid question.
You need to make the List_Departments method return an object that has a ToHtml method.
Depending on what your exactly methods are returning, you might make a class called something like ObjectList, which would have a ToHtml method, and have the ListDepartments and ListCategories return instances of it.
Alternatively, and especially if your methods are returning existing classes such a DataTable, you could make an extension method for that class called ToHtml.
It sounds like what you're referring to is Extension Methods
Basically, your functions List_Departments() and List_Categories are returning some typed object correct? That being, the object returned would have to have a Method created in it's class definition called ToHTML(). If the two functions return the same type of object then, you only need to define it once. If they return two different types, then you will have to define the ToHTML() method on both return types class definitions.
Unless I'm missing something here, these two functions don't require the static modifier.
If the returning types are types that you don't have source code access to, then you can define an extention method for each type that will process the type of object being returned and can display the ToHTML() for it.
You didn't supply much info, but using Extension methods seems a good approach to me.
An example turning an string into an int:
public static class StringMethods {
public static int ToInt(this String subject) {
int result;
int.TryParse(subject, result);
return result;
}
}
Assuming List_Departments returns Department:
public static class DepartmentMethods {
public static string ToHtml(this Department subject) {
// Whatever you want to do.
}
}
If you do have acces to the internals of the type returned by List_Departments, you can also just add ToHtml there.
the search term you're looking for is Method Chaining :-)
http://www.bing.com/search?q=method+chaining
This is something along the lines of what jQuery does. Basically, you make an object that has all of the methods that you want to be able to chain. Then, using the builder pattern, you can chain all the calls together until you call some final "result" method (ToHtml in your case).
public class Inventory
{
private IEnumerable<Departments> departments;
private IEnumerable<Items> items;
public Inventory ListDepartments()
{
// load up departments to a class level field
return this;
}
public Inventory ListItems()
{
// load up items to a class level field
return this;
}
public string ToHtml()
{
// convert whichever enumerable was previously loaded to HTML
return stringBuilder.ToString();
}
}
That lets you do things such as:
inventory.ListDepartments().ToHtml();
The ToHTML() function is a function that acts on the type returned from List_Departments()
For example:
if Inventory.GetProduct(0) returns an int. You can use Inventory.GetProduct(0).ToString() because ToString() is a method of an integer type.
In order to do this, List_Departments() would have to return a custom object that has a method called ToHTML() say
public class Department() {
public HtmlDocument ToHTML() {
//Create the html document to return here
}
}

Categories