I have a file that looks like the following:
public abstract class TestStep
{
public abstract bool DoWork();
public abstract List<TestStep> PrerequisiteSteps { get; set; }
public abstract string DisplayForm { get; }
}
class TestFunctions
{
public class A : TestStep
{
public override string DisplayForm { get { return "MainForm; } }
// remaining implementation goes here...
}
public class B : TestStep { // some implementation }
public class C : TestStep { // some implementation }
public static void NextStep() { }
}
I'd like to serialize the classes A, B, and C to an XML file. I can manually add instances of these classes to a List<TestStep> object and pass that to an XML serializer, but I'd like to programmatically accomplish this because I might add or remove classes in TestFunctions in the future. As a result, I've found that I can use reflection to get an array of the functions:
Type type = (typeof(TestEngineFunctions));
Type[] testEngineFunctions = type.GetNestedTypes(BindingFlags.Public);
However I'm not sure how to proceed from here. I have access to the name of the functions, I can get their properties as well, but ultimately I don't have an actual object to serialize.
Am I on the right track or is there another method better suited for this?
You can get a new instance of the objects like this:
ObjectType instance = (ObjectType)Activator.CreateInstance(objectType);
Since you may not know the ObjectType before run time you could use the dynamic type and don't cast:
dynamic instance = Activator.CreateInstance(objectType);
However, if you attempt to serialize right after you instantiate you'll just get the default values of the object in your XML.
Related
I would like to avoid writing the same line of code in all my derived classes. I have the following structure:
using Newtonsoft.Json;
public class BaseClass
{
public string BaseProperty { get; set; }
public string Serialize() { return JsonConvert.SerializeObject(this); }
}
public class DerivedClass : BaseClass
{
public string DerivedProperty { get; set; }
}
What happens when Serialize() is called from DerivedClass? Is this smart enough to know that the child object contains an extra property? Or, am I limited to writing this same line of code in each child of BaseClass?
Some language features / behaviors are easy to experiment with... Considering the following code:
public class A
{
public string WhoAmI => this.ToString();
}
public class B:A { }
Your question is equivalent to asking what Console.WriteLine(new B().WhoAmI) prints out?
Well, if in doubt, run it and see... it takes less than 1 minute.
this is a reference to an object, and behaves as any other reference, it simply has a special name.
Considere the following:
A a = new B();
Now you have a B instance referenced by an A typed reference a, but the instance is still a B. In your case this inside BaseClass is simply a BaseClass reference to whatever instance has been created. Do not confuse the type of a reference pointing to an object with the type of the object itself, they need not be the same.
[MAJOR EDITS, my first post was somewhat misleading. My appologies]
Given a class such as:
public class DatabaseResult{
public bool Successful;
public string ErrorMessage;
//Database operation failed
public static DatabaseResult Failed(string message) {
return new DatabaseResult{
Successful = true,
ErrorMessage = message
};
}
}
How can I implement subclasses such that I can add additional properties to represent data relevant to the particular operation (such as MatchedResult in the case of a SELECT type query) without the need to implement that static failure function? If I try to use plain inheritance, the return type will be of the parent class. Eg:
DoThingDatabaseResult : DatabaseResult {
public IEnumerable<object> SomeResultSet;
public static Successful(IEnumerable<object> theResults){
return new DoThingDatabaseResult {
Successful = true,
ErrorMessage = "",
SomeResultSet = theResults
};
}
//public static DatabaseResult Failed exists, but it's the parent type!
}
The goal is to avoid needing to copy the Failed static function for every subclass implementation.
Make it recursively generic:
public class BankAccount<T> where T : BankAccount<T>, new()
{
public T SomeFactoryMethod() { return new T(); }
}
public class SavingsAccount: BankAccount<SavingsAccount>{}
You'll note that I made the factory method non-static, because static methods aren't inherited.
You can't do this exactly as you have defined the question. The best way to tackle this is really to pull your factory out of the class completely:
public class BankAccount
{
}
public class SavingsAccount : BankAccount
{
}
public static class BankAccountFactory
{
public static T Create<T>() where T : BankAccount, new()
{
return new T();
}
}
Now the Factory has no dependency on the actual type. You can pass any derived class of BankAccount and get it back without doing any extra work or worrying about inheriting your factory method.
If I may, I'd like to expand upon StriplingWarrior. In fact, you can use static for the factory. This following code shows that a and c are the expected object types. The limit is you cannot use the factory on the base class itself.
private void Testit()
{
var a = SavingsAccount.Factory();
var c = CheckingAccount.Factory();
//var b = BankAccount.Factory(); //can't do this
}
public class BankAccount<T> where T : BankAccount<T>, new()
{
public static T Factory()
{
return new T();
}
}
public class SavingsAccount : BankAccount<SavingsAccount>
{
}
public class CheckingAccount : BankAccount<CheckingAccount>
{
}
In order to use inheritance, you need an instance of an object and a member of that object. In this case, for the object we can't use BankAccount/SavingsAccount because then we would already have what we're trying to get. This means we need an actual factory object, which is what most people are talking about when they talk about a factory. So if we pull that out into a Factory and use inheritance...
public class BankAccountFactory { public virtual GetAccount() { return new BankAccount(); } }
public class SavingsAccountFactory : BankAccountFactory { public override GetAccount() { return new SavingsAccount(); } }
But now how do we get an instance of the proper type? We've just pushed our problem one layer deeper.
Instead, what you probably want to do, is use some sort of configuration to determine the type, or pass the type you want into a method.
public BankAccount GetAccount(AccountType type) { /* */ }
or
public BankAccount GetAccount() { /* Access config */ }
For a simple answer to your question: You don't need to use generics or anything like that, you just need your method to not be static...
Class:
public class ClassNameA :ISomeInterface {
}
public class ClassNameB :ISomeInterface {
}
From javascript:
var reqP = { 'Id': id, 'Name':name };
var ReqParams = { 'ReqParams': reqP };
var obj = { 'ClassNameA': ReqParams };
makeAjaxCall("POST",
JSON.stringify(obj), '/ControllerName/someMethod/', 'html',
Action method looks like:
public ActionResult someMethod(object obj){
// call comes to this method but obj is not populated.
}
public ActionResult someMethod(ISomeInterface obj){
// call comes to this method but throws exception.
// Exception : Cannot instantiate interface. but i am passing class object.
}
from JavaScript I will pass object of a concrete class type which implements ISomeInterface so that I can have multiple implementations. Concrete Class can of any one of the two types.
Any Suggestions?
That won't work. The model binder needs a concrete type to be able to create an instance and bind the values.
object is a concrete type and can be created using Activator.CreateInstance, but it doesn't have any properties that will match the data you receive.
The interface (or abstract types) cannot be created, since they're not concrete types. It's a simple as that.
If the JSON contained some hint about the type, it migth be possible to implement a custom model binder to create the instances for you. You can read more about the model binding process here.
The default model binder is not going to be able to figure out what to do. Let's just go through the exercise with some sample interfaces to show why. Say you have this:
public ActionResult SomeMethod(ISomeInterface obj)
{
// ...
}
...and say you have these two implemenetations:
class ClassA : ISomeInterface
{
public string Name { get; set; }
public string Phone { get; set; }
}
class ClassB : ISomeInterface
{
public string Name { get; set; }
public string Email { get; set; }
}
...and say this JSON is posted:
{ "Name": "Some Value" }
How would the model binder know which class to use? Would it search all defined classes in all assemblies to find all implementations of the interface? And if so, even if it had smart selection logic based on properties, how would it select between ClassA or ClassB, both of which are compatible?
What you may want to do is either use a type like Dictionary<string, object> that you know will be compatible, dynamic, or go with a concrete class that is a union of everything you need. Alternately, you can create a custom model binder with its own logic for selecting the class you want to instantiate. See this question for more details.
I have a set of classes that derive one from another and the lower level has complete structure of what i need. the data stored and save is the highest level. in the highest level the Type is stored in the object. how can i cast down the highest level to the lowest. the generic see highest and T is highest which isn't helpful.
example :
Head class with couple core methods/fields :
[Serializable()]
public class CSelectionProperties
{
private Dictionary<string, string> lstProperties = new Dictionary<string, string>();
public Dictionary<string, string> getProperties { get { return lstProperties; } }
private Type objectType = null;
public Type ObjectType { get { return objectType; } set { objectType = value; } }
internal string FindProperty(string sProperty)
{
return FindProperty(sProperty, null);
}
internal string FindProperty(string sProperty, string sNullValue)
{
string sValue = sNullValue;
lstProperties.TryGetValue(sProperty, out sValue);
}
}
here an example of one of the many derived class :
[Serializable()]
public class CFilterSelectionProperties : CSelectionProperties, IFilterSelectionProperties
{
public double getAirVolume()
{
return Convert.ToDouble(FindProperty("INCFMValue", "0"));
}
}
Now all object using these property have the variable as CSelectionProperties so we can reuse everywhere same format.
When a class such as CFilterSelectionProperties gets created the Type get stored into the CSelectionProperties.ObjectTypeas a Type now another project receive a collection of CSelectionProperties and to properly read them i need to cast them as the proper type.
Right now i am going the old way
If(item is CFilterSelectionProperties)
{
RunDataAnalysis(item as CFilterSelectionProperties);
}
Else If (item is ...)
{
RunDataAnalysis(item as ...);
}
i use reflection and i stumble upon a case where i need the actual original class to loop the methods and retrieve some data. is there any way ?
Also some report will need to be open but again i have 4 class that derive from 1 single class that derive from CSelectionProperties at which point i don't have access to anything at all. I'm just trying to get away from If/Else which works fine.
As side note i tried going with and Activator but i can only find how to recreate a class as child type.
CFilterSelectionProperties oItem = new CFilterSelectionProperties();
MyObject.SelectionProperties = Activator.CreateInstance(oItem.ObjectType) as CSelectionProperties;
Not exactly sure if this is what you need but you can have a base class that "knows" the derived type:
class MyBase<T> {}
class A : MyBase<A> {}
class B : MyBase<B> {}
this way you can do this:
void Foo(MyBase<T> baseObj)
{
T derived = (T)(object)baseObj;
// use derived in a strongly-typed manner
}
Without knowing what RunDataAnalysis does it sounds like you can use virtual (or abstract) methods/properties in the base class that are overloaded in the derived classes. Then when you call those methods/properties in RunDataAnalysis you will be using the most derived version without having to cast the variable.
For example:
public class CSelectionProperties
{
... existing stuff
public virtual DataSet GetData(.. some parameters ...)
{
.. do stuff common to ALL subtypes
}
}
and
public class CFilterSelectionProperties : CSelectionProperties, IFilterSelectionProperties
{
public override DAtaSet GetData(... some parameters ...)
{
... do stuff common to THIS type and subtypes
}
}
Lots of questions with these keywords; I sifted through the first 30 or so then gave up.
I have interfaces like so:
public interface IColumnRule
{
int Length { get; set; }
string Name { get; set; }
object Parse(string toParse);
int Position { get; set; }
Type Type { get; }
}
public interface IColumnRule<T> : IColumnRule
{
ColumnRule<T>.RuleFluentInterface<T> Configure { get; }
new T Parse(string rowdata);
Func<string, T> ParsingFunction { get; set; }
}
... the idea being, one would implement the IColumnRule<T> to create a strongly-typed column parser utilizing the Func<string, T>.
The problem is, I store these IColumnRule<T> concretes in an IList<IColumnRule> container. There are multiple types of IColumnRule<T>, each implementing on a different type. When I invoke the Parse method on the IColumnRule interface, I am expecting the new Parse(string) method of the subclass to be called, but the base Parse is the one actually being called.
How can I invoke the subclass generic T Parse(string) method from a collection of IColumnRule using the interface's object Parse(string) ... or is this impossible?
Your implementation of IColumnRule<T> would have to provide a compliant Parse method. Given your code, the easiest way to do that is with an protected abstract method in your base class which is overridden in your subclass.
public abstract class ColumnRule : IColumnRule
{
...
public object Parse(string rowdata)
{
return this.ParseInternal(rowdata);
}
protected abstract object ParseInternal(rowdata);
}
public class ColumnRule<T> : ColumnRule, IColumnRule<T>
{
...
public new T Parse(string rowdata)
{
// strong-typed parse method
}
protected override object ParseInternal(string rowdata)
{
return this.Parse(rowdata); // invokes strong-typed method
}
}
When I invoke the Parse method on the IColumnRule interface, I am expecting the new Parse(string) method of the subclass to be called, but the base Parse is the one actually being called.
Yes, it would. You've got two methods which are unrelated as far as the type system, CLR and compiler are concerned.
How can I invoke the subclass generic T Parse(string) method from a collection of IColumnRule using the interface's object Parse(string) ... or is this impossible?
The simplest approach would be to have an abstract class implementing this as:
public abstract ColumnRuleBase<T> : IColumnRule<T>
{
public object Parse(string toParse)
{
IColumnRule<T> genericThis = this;
return genericThis.Parse(toParse);
}
...
}
(If you had the two method names being different, it would be slightly simpler.)
You'd have to know the type somehow:
List<IColumnRule> rules; // populated from somewhere
foreach (IColumRule<int> rule in rules.OfType<IColumnRule<int>>()) {
int foo = rule.Parse(rowData);
}
Or just cast a known element:
int foo = ((IColumnRule<int>)rules[5]).Parse(rowData);