create an object depending on the caller object - c#

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.

Related

Can I dynamically choose the type of a LiteCollection<T> in a method signature?

I have a custom class Customer and inside another class a method that returns a list based on a LiteCollection from LiteDB typized using the Customer class in the signature. What I wanted to know is if it’s possible creating a method that dynamically chooses which class uses a type, meaning if I can pass as a parameter the class type of the LiteCollection to return when I call the method.
The code is as follows:
public static LiteCollection<Customer> GetCustomers()
{
var collection = ConnectToDB().GetCollection<Customer>("customers");
return collection;
}
How about:
public static LiteCollection<T> Get(string tableName)
{
return ConnectToDB().GetCollection<T>(tableName);
}
That would be called:
var table = Get<Customer>("customers");
Update
Unfortunately it is not really possible to get rid of the generic type, cause otherwise your consuming code doesn't know what it gets back. So the minimum that would be possible would be
var table = Get<Customer>();
In that case your implementation needs some kind of mapper from type to table name. For this purpose I could think of three possibilities (which you could also combine):
The class has an internal Dictionary<Type, string> where all table names for a given type is manually entered.
The convention is that for every T the table name is a pluralized string of the type name, then you need a pluralize method that returns Pluralize(typeof(T).Name).
By reflection you iterate over your derived DBContext, get out all DBSet<> properties and pre-fill the dictionary out of the first possibility by using the generic argument from DBSet<> and the property name.

Can you invoke a method of an object using a string? [duplicate]

I have a number of 'jobs' in my application, where each job has a list of methods which it needs to call, along with it's parameters. Essentially a list containing the following object is called:
string Name;
List<object> Parameters;
So basically, when a job runs I want to enumerate through this list, and call the relevant methods. For example, if I have a method like the following:
TestMethod(string param1, int param2)
My method object would be like this:
Name = TestMethod
Parameters = "astring", 3
Is it possible to do this? I imagine reflection will be the key here.
Sure, you can do it like this:
public class Test
{
public void Hello(string s) { Console.WriteLine("hello " + s); }
}
...
{
Test t = new Test();
typeof(Test).GetMethod("Hello").Invoke(t, new[] { "world" });
// alternative if you don't know the type of the object:
t.GetType().GetMethod("Hello").Invoke(t, new[] { "world" });
}
The second parameter of Invoke() is an array of Object containing all the parameters to pass to your method.
Assuming the methods all belong to the same class, you could have a method of that class something like:
public void InvokeMethod(string methodName, List<object> args)
{
GetType().GetMethod(methodName).Invoke(this, args.ToArray());
}
If you're using .NET Framework 4, look at dynamic, otherwise GetMethod and then call Invoke of MethodInfo.
Use MethodBase.Invoke(). Should work down to .NET 2.0 with System.Reflection.
If you're using having to resort to reflection, there is probably a better way to accomplish your task. It may take a little more architecture, but it's doable.
Remember, having more code isn't a bad thing -- especially when it compliments the readability and manageability of your code. Reflection is difficult to understand for most, and you lose most of your compile time type safety. In your example, you could probably just get away with a switch statement and distinct objects for each method you were planning to call. e.g.
// Have some object hold the type of method it plans on calling.
enum methodNames
{
Method1,
Method2
}
...
class someObject
{
internal methodNames methodName {get; set;}
internal object[] myParams;
}
...
// Execute your object based on the enumeration value it references.
switch(someObject1.methodName)
{
case Method1:
Test.Method1(Int32.Parse(someObject1.myParams[0].ToString),someObject1.myParams[1].ToString());
break;
...
}
If you know that you only have a distinct set of method possibilities to call, why not just set yourself up ahead of time?
NuGet to the rescue! PM> Install-Package dnpextensions
Once you have that package in your project, all objects should now have a .InvokeMethod() extension, that will take the method name as a string and any number of parameters.
That does technically use "magic strings" for the method names, so if you wanted to strongly-type your method dictionary, you could make the keys of type MethodInfo and get them like this...
MethodInfo[] methodInfos = typeof(MyClass).GetMethods();
And then you can do something like this...
var methods = new Dictionary<MethodInfo, Object[]>();
foreach (var item in methods)
item.key.Invoke(null, item.value);
// 'null' may need to be an instance of the object that
// you are calling methods on if these are not static methods.
Or you could do some variation of the above block using the dnpextensions I mentioned earlier.

Calling Static Derived Class Method from Static Base Class Method

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 :(.

Using extension methods with runtime assemblies

Is there any way to use extension methods on a class that has been dynamically created using Relection.Emit? For example:
class somewhere
{
somewhere()
{
// define the type here using ReflectionEmit, etc.
Type tableType = CreateTableType(...table parameters...);
var table = Activator.CreateInstance(tableType);
table.Shuffle();
}
}
//... elsewhere
public class static TableTypeExtensions
{
public static Table Shuffle( this Table t)
{
...
}
}
But I don't have the class by name "Table", only Type tableType available.
Is there any way around this?
Thanks
Make the dynamic class implement an interface (an empty one if you want), add extensions to the interface.
Define a common base class for your TableType and define the extension method on that. This way your extension method should be available for the derived classes as well.
Let's look at what you're asking.
You're asking how to get the extension method to operate on your object instance.
Obviously, for this to work, it has to be a Table, otherwise your question makes no sense.
So just cast it to Table:
var table = (Table)Activator.CreateInstance(tableType);
and you can call your extension method just fine.
In your somewhere code do you have reference to the type Table? If so you can:
Type tableType = CreateTableType(...table parameters...);
var table = Activator.CreateInstance(tableType) as Table;
table.Shuffle();

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