I've read many posts trying to accomplish similar tasks but cannot find a proper solution to my problem.
I'm trying to dynamically cast an object at runtime. (I know a lot of you are going to say it can't be done, and I'm not actually sure if it can...) My problem is that I have a dynamically created TreeView in a Windows Forms Application to display an Org Chart.
The data in the TreeView pulls from 3 tables: Departments, Jobs, Employees.
Importing the Tables as a Local DataSource gives me all 3 Tables as DataSet Objects, and templates for DataRow objects type casted to the table it comes from (including all columns as properties). (Similar to linq - except for Oracle DB)
I create TreeNode objects, use a description field from my DataRow as the TreeNode.Text Property and then attach the DataRow itself as the TreeNode.Tag property. This way, I can access the data from directly within the TreeNode simply by casting:
dsMyDataSource.DepartmentRow =
(dsMyDataSource.DepartmentRow)treeview1.SelectedNode.Tag;
I have a method that runs whenever the User selects a Node on treeview1 that populates a Details window with some of the underlying objects data. As of right now, I have a single method with a switch statement as such:
private doSomething()
{
switch(treeview1.SelectedNode.Tag.GetType().Name)
{
case "dsMyDataSource.DepartmentRow":
dsMyDataSource.DepartmentRow department =
(dsMyDataSource.DepartmentRow)treeview1.SelectedNode.Tag;
lblDetailsTitle = department.Title;
break;
case "dsMyDataSource.JobRow":
//etc...
}
}
What I want to do, is to have overloaded methods for each type and get rid of my switch statements. Like so:
this.doSomething(treeview1.SelectedNode.Tag);
Problem is, this returns a base object (thus the cast). But I don't know at compile time what type of TreeNode the User will select. Thus I want to be able to do something like:
this.doSomething((treeview1.SelectedNode.Tag.GetType())treeview1.SelectedNode.Tag);
private void doSomething(dsMyDataSource.DepartmentRow department)
{
lblDetailsTitle = department.Title;
// etc...
}
private void doSomething(dsMyDataSource.JobRow job) {..}
private void doSomething(dsMyDataSource.EmployeeRow employee) {..}
Is this possible?
You might find things cleaner if you use some meaningful objects rather than working directly off DataRows. In addition this will let you add a base class, which will make your casting problems go away.
So for example you could have
abstract class Selectable
{
public string Type { get; private set; }
public Selectable(string type) { Type = type; }
abstract void doSomething();
}
and then a type for each thing you want to select
class Department : Selectable{...}, class Job : Selectable{...}
To get the base types you will need one switch in a factory object.
public static class SelectableFactory
{
public static Selectable GetFromDataRow(DataRow dr)
{
Selectable res = null;
switch (dr.Type)
{
case "Department":
res = new Department(dr);
// etc ...
}
}
}
But you now have a collection of Selectables that can use polymorphism to do the action.
In addition to making your life easier it will make your code much easier to parse for anyone else that has to work on it in the future. It's also extensible, so when you need to add a DoSomethingElse method it's much easier to add for everything - or when you need a new type of datatable you don't disturb your UI code.
Related
Not sure I'm able to formulate this question in a way someone would simply understand, so lets have a cool marketing example:
public class Part
{
public MemberType member;
...
}
public class Product
{
public Part part1;
...
}
...
Product product = new Product();
I need to modify the public product's part1. So, the natural method is to write something like:
product.part1 = new Part();
Now, an algorithm (let's say a sort of search one) would go through the product object and identify the part1 as an interesting part and returns reference to it:
Part Search(Product product)
{
Part part = null;
...
part = product.part1;
...
return part;
}
...
interesting_part = Search(product);
We can alter the product object via the interesting_part like
interesting_part.member = whatever;
Now, the question: in c/c++ if the Product.part1 is pointer to Part and Search returns address of this pointer, we could replace the part1 just by assigning new value to this address. AFAIK this is not possible for c# reference:
interesting_part = new Part();
Just creates new object and copies its reference to the interresting_part, but without knowing the member parent (product object), we are not able to modify the (product.part1) reference, just its content. We would need second level of the reference.
Is there something like "ref reference" type which would accept reference addresses? In such hypothetical case the search would return ref Part and assigning to such value would replace the referenced object with the new one.
Thanks.
You could create a Reference class
class Reference<T>
{
private Func<T> m_Getter;
private Action<T> m_Setter;
public Reference(Func<T> getter, Action<T> setter)
{
m_Getter = getter;
m_Setter = setter;
}
public T Value
{
get{return m_Getter();}
set{m_Setter(value);}
}
}
Now you can say
Reference<Part> Search(Product product)
{
Part part = null;
...
part = product.part1;
var reference=new Reference<Part>(()=>product.part, (value)=>product.part1=value);
return refernce;
}
var partReference = Search(product);
partReference.Value = someNewPart;
In a very similar situation, I keep a reference of the parent in each child object. Simple and works.
public class Part
{
public MemberType member;
...
public Product parent;
Part(Product p)
{
parent = p;
}
}
public class Product
{
public Part part1;
...
}
I don't think you can do that. You would need to mutate a reference to you product object, or have some other added layer of reference.
So you need to build a Proxy object. The Product would get a reference to the Proxy and the (hidden) Part can be exchanged. This is a common OO design pattern. Of course the Proxy can delegate method calls to the Part.
If you want to change the field, you can do this,
class Program
{
static void Main(string[] args)
{
var holder = new Holder();
holder.CurrentPart = new Part() { Name = "Inital Part" };
Console.WriteLine(holder.CurrentPart.Name);
TestRef(ref holder.CurrentPart);
Console.WriteLine(holder.CurrentPart.Name);
Console.ReadKey();
}
public static void TestRef(ref Part part)
{
part = new Part() { Name = "changed" };
}
}
public class Part
{
public string Name;
}
public class Holder
{
public Part CurrentPart;
}
This won't work with property, indexers and so.
As far as I know, there isn't any way to alter an object's "parent" without having a reference to it. So I believe the official answer to your question as written is "no".
That said, there are many ways to accomplish the task as written. The easiest option is to add a reference to the parent from the part object. You end up with something like:
public class Part
{
public Product parentProduct;
public MemberType member;
...
}
Now whenever you have a part object you also know what product the part goes with (IF it does indeed go with a part at all). This is not necessarily a bad coding style but there certainly are pitfalls. You can update the product, but forget to update the parts in that product, you are coding so that parts have one product, but what if that part has many products? You can see how this works, but it can get complicated.
Taking this and making it more generic you can have reference the parent as an object type. That looks like:
public class Part
{
public object parent;
public MemberType member;
...
}
Now when you want to use the parent you can write something like:
var parentProduct = myPart.parent as Product;
This will convert the parent to a product or will assign null if the parent is not of the type Product. Now parts can have parents of any given type you would want and you have made the pattern more flexible.
One final pattern I know people use frequently is delegates. This allows you to pass in a function effectively modifying the way "search" is working. Say what you really want to do is search, then process the results in some manner, but you want that processing to be flexible (this may be what you were doing with the results). In that case, you can use delegates as follows:
// define the delegate
public delegate void ProcessResultDelegate(Product result, Part interestingPart);
// an example search function
public static void RunSearch(IEnumerable<Product> products, ProcessResultDelegate processingHelper)
{
// run the search... then call the processing function
processingHelper(searchResult, interestingPart);
}
This pattern is more useful when you want to modify the behavior of a routine rather than the return value from that routine.
Anyways, hope these patterns help some!
I have 2 already defined classes, we'll call them DogActivityType and HorseActivityType.
They have the same fields, same methods, but they write to 2 different tables in the database, and of course, are named differently.
I have a function with all the business rules already working for one class, and the other class uses the same business rules.
Restrictions:
I have to use these 2 classes since they are used throughout other parts of the project
I can't create one class and add another column (field) to distinguish between both types of classes.
I can't edit the source for these 2 classes.
.
Here is my simplified version of the code:
public doAllCalculations(){
// retrieve collection
foreach (DogActivityType activity in allActivities){
// a lot of code here
// more code...
createMoreOf(activity); // this is overloaded since it needs to know which DB to write to
}
}
// using overload for same function name
private createMoreOf(DogActivityType doggyActivity){
/// do some specific when it is a dog
}
private createMoreOf(HorseActivityType horse){
/// do some specific when it is a horse
}
Now, the problem is: doAllCalculations() is very extensive and complicated and may change during the course of development. I don't want to have 2 different functions (doAllCalculationsDOG() and doAllCalculationsHORSE() ) in order to do the same analysis, just because I need one for the Dog and another for the Horse class. One day someone in the project may forget to update both functions or any other bad scenario...
So, I want to use the same function for both classes. So if I edit a rule in the big calculation function, I will know it works for both classes.
I'm thinking I'll end up with something like this:
public class AnimalActityType {
}
public doAllCalculations(){
// retrieve collection
foreach (AnimalActivityType activity in allActivities){
// a lot of code here
// more code...
createMoreOf(activity);
}
}
AnimalActityType will simulate an abstract parent, I'll call it reverse polymorphism...
But how do DogActityType and HorseActityType know about this parent? Can I force the parent?
Is it possible? Any ideas?
I can't edit the source for these 2 classes.
Assuming this means you can't create a base class or even an interface to me this says that even if you come up with a solution it's going to be nothing but a messy hack job. I'd sooner try to find a way around this self imposed restriction than come up with some perverted form of polymorphism.
you can try to use decorator pattern, but in very unusual way.
class Decorator
{
private object instance;
public Decprator(object instance)
{
this.instance = instance;
}
public <type> SomeCommonProp
{
get{
if(instance is DogActivityType)
{
return (instance as DogActivityType).SomeValueOrPropertyOrCall;
}
else
{
return (instance as HorseActivityType).SomeValueOrPropertyOrCall;
}
}
}
}
class MyCalculations
{
private Decorator instance;
public MyCalculations(Decorator inst)
{
instance = inst;
}
public <type> SomeCalculationMethod()
{
// here you will use instance.SomeCommonProp for your calculations
}
}
I have a data object which has a base class with three derived classes,
public enum ModelType
{
A,
B,
C
}
public abstract class Parent
{
protected ModelType type;
}
public class ChildA: Parent
{
private new ModelType type = ModelType.A;
}
public class ChildB: Parent
public class ChildC: Parent
The same type field is in the other 2 children with corresponding ModelTypes.
I have another layer between the forms that has some higher level additional information about the data object and an instance of Parent(). I am trying to simplify the problem a lot so I apologise if I am not being clear and have not given enough information.
public enum UIModelType
{
A,
B,
C,
None
}
public class DataObject
{
private Parent someData;
private UIModelType type;
}
The fields have getter and setter properties.
The UI only communicates with the DataObject class and cannot see the lower level someData object.
Now at some point during the UI (which is a wizard to fill in the information in the data objects), the user can select A, B or C. My problem is how to communicate this information without too much code repetition. Right now I have an enum between the UI and DataObject class. So if user selects A, it assigns a data type as A using the enum. The DataObject class now instantiates the someData object with ChildA(). The problem is to communicate between the DataObject and someData object I have another enum with A, B and C to communicate the type.
Would it be healthier to use typeof instead, although I have read that that is not the best way to go.
I need to do many equality checks with the data type (ABC) from the UI all the way to the lower level data object and hence I had thought enums is the fastest way but it doesn't feel right to have so many enums of the same type in different classes. Am I missing something very obvious here?
Rather than using typeof or enum, you could use is.
private Parent someData = new ChildA();
if (someData is Parent) { } // Returns true.
if (someData is ChildA) { } // Returns true.
if (someData is ChildB) { } // Returns false.
However, if I understand your question correctly, it sounds like you're doing these checks because you need to continually downcast the someData object to provide functionality for the DataObject class that depends on the type of someData. If this is the case, you might want to consider refactoring your code, as repeated downcasting can can make code difficult to read and defies some traditional concepts of object-oriented programming.
Edit:
Ok, I think I understand your question better, now. You're looking for a better way of creating children of the Parent object (i.e. using the factory pattern) than by using an enum.
You could create the instance dynamically based on the type name:
var typeName = GetTheTypeTheUserWants();
var type = System.Type.GetType(typeName, false, true);
if (type == null) throw new Exception();
var someData = Activator.CreateInstance(type) as Parent;
if (someData == null) throw new Exception();
Using an enum might be easier, but this method allows you to create new subclasses of Parent without updating your enum.
If I still missed the point of your question, sorry.
Just use 'typeof' and be done with it. It sounds like you are only using enums because of some tiny increase in performance that you might get. Just go with whatever produces the easiest to read / maintain code (typeof in this case).
I don't think that you have to worry about performance in your wizard because the slowest part is going to be the user selecting what type of object they want.
I would get rid of ModelType. You're just creating another way to represent information you already have, which will just be annoying to maintain.
In your DataObject class, your UIModelType could go away too. Wherever you thought you were going to use it could probably be replaced with:
if (this.someData is ChildA) {
} else if (this.someData is ChildB) {
} ...
I have a Report Interface which has a Run method.
There are different types of reports which implement this interface and each run their own kind of report, getting data from different tables.
Each report, using its own data context, gets data which then populates Business Objects with and at the moment they are returned as an array (I would like to be able to at least return something like a list but because you have to define the list type it makes it a bit more difficult).
Reflection is then used to find out the properties of the returned data.
I hope I have explained this well enough!
Is there a better way of doing this?
By request:
public interface IReport
{
int CustomerID { get; set; }
Array Run();
}
public class BasicReport : IReport
{
public int CustomerID { get; set; }
public virtual Array Run()
{
Array result = null;
using (BasicReportsDataContext brdc = new BasicReportsDataContext())
{
var queryResult = from j in brdc.Jobs
where j.CustomerID == CustomerID
select new JobRecord
{
JobNumber = j.JobNumber,
CustomerName = c.CustomerName
};
result = queryResult.ToArray();
}
}
}
The other class then does a foreach over the data, and uses reflection to find out the field names and values and puts that in an xml file.
As it stands everything works - I just can't help thinking there is a better way of doing it - that perhaps my limited understanding of C# doesn't allow me to see yet.
Personnally I would first ask myself if I Really need an interface. It would be the case if the classes implementing it are Really different by nature (not only by report kind).
If not, i.e all the implementing classes are basically "Reporters", then yes, there is a more convenient way to do this which is :
Writing a parent abstract Report
Having a virtual Run method and the CustomerID accessor
inheriting your "Reporter" classes from it
I am not a big fan of datasets so I use POCO to return data. I have achieved paging and sorting using custom methods that I create for a POCO type that work on page size and give me a set of the complete POCO collection at a time, I use methods that check for name of the DataItem clicked and sort order to do that sort. Creating such methods over and over for every POCO that you plan to use with an ASP.net data control like Gridview is pretty painful.
Is there a technique to automate this so that I do not need to make such methods every time for a new POCO so that it works as if you were using a DataTable? I can provide some more explanation if required.
NOTE: Some people may call POCO as DTOs .
EDIT : I found this article on this topic. Is this the only possible way to get to what i am trying to do??
I agree with the base class idea as this will save all the duplicate code. One thing I did that takes a step in this direction is to create a class to handle the sorting of any generic list (for DTO/POCO). This allowed me to sort a list in my presenter or code-behind with only 1 line of code.
Typically for SortExpression I return the property name of the DTO you want to sort on. In addition, the SortDirection would be a simple "Ascending" Or "Decending"
List<Supplier> SupplierList = mSupplierService.GetSuppliers();
SupplierList.Sort(new GenericComparer<Supplier>(mView.SortExpression, mView.SortDirection));
mView.Suppliers = SupplierList;
Here is the class I used
public class GenericComparer<T> : IComparer<T>
{
private string mDirection;
private string mExpression;
public GenericComparer(string Expression, string Direction)
{
mExpression = Expression;
mDirection = Direction;
}
public int Compare(T x, T y)
{
PropertyInfo propertyInfo = typeof(T).GetProperty(mExpression);
IComparable obj1 = (IComparable)propertyInfo.GetValue(x, null);
IComparable obj2 = (IComparable)propertyInfo.GetValue(y, null);
if (mDirection == "Ascending") {
return obj1.CompareTo(obj2);
}
else {
return obj2.CompareTo(obj1);
}
}
}
I created an Entity base class. My DAOs derive from it and have properties corresponding to the table columns (for the most part). My DAL returns List for any query and that is bindable to a GridView.