How to pass object attributes as function parameters? - c#

I am designing a 3 layer framework
I would like to know if It's possible to pass attribiutes of an object to a function without declaring them explicitly ?
For example If I want to pass Id,Name to personnelBL.ValidateInsert(...)
I don't want the ValidateInsert function interface look like this : ValidateInsert(Id,Name)
The reason for that is that I want to write a base abstract class to contain a ValidateInsert(...)
abstract function so I will Inherit from that class in my BL Layer classes and If the ValidateInsert input parameters could be declared in a way that I could pass an object attribiutes in a general form It would really be nice .
Note: Someone might say that I can pass an object to the function using generics but I really don't want to pass an object ! I want to pass any object's attribiutes so I can Inherit that abstract base class in any entityBL classes .
I really could not explain what I want better ! Sorry for that and thanks for understanding me .

not sure that I fully understand what you want , but I think the below can help
You can use reflection.You can avoid the performance issues, is you create method per class on the fly and compile it (can use compile expression tree). and add your own attribute that you put only on relevant attributes.
Create an Interface, It can return dictionary of column name and their values. your abstract class will implement this interface.
hope this answer your question

I am not sure if i understand your question correctly, but are you looking for something similar to this-
public class Base<T, TFiled>
{
public void ValidateInsert(TFiled filed)
{
}
}
public class Derived : Base<Derived, long>
{
public long Id { get; set; }
}
public class AnotherDerived : Base<Derived, string>
{
public string IdSring { get; set; }
}
public class MyObject
{
private Derived d = new Derived();
private AnotherDerived anotherIsntance = new AnotherDerived();
public MyObject()
{
d.ValidateInsert(10);
anotherIsntance.ValidateInsert("some string");
}
}

Well, not really.
But you can get very close to!
You can use the Expression API. It's awesome. The code I'll post here is just pseudocode but you'll get the idea. I'll not worry about syntax but I'll try the hardest I can.
public static bool ValidateInsert(params Expression<Func<object,object>>[] properties)
{
//Here you'll do some code to get every property. You can do a foreach loop.
//I think you will need to use reflection to get the property values
} //Change Func<Object,Object> accordingly. This represents a function that takes an object and returns another object.
This is how you can achieve the syntax, but I'm not sure about functionality.
You'll need an "instance" object where you'll get the properties values from.
So, you could call it like this:
ValidadeInsert(x => x.Id, x => x.Name, x => x.Whatever)
Here you can see how to get the Getter method of a property. I think you can get the PropertyInfo from the lambda expression, but I'm not sure. You'll have to do some research and adapt it to your code, if you decide to follow this way.
Sorry about my english, but I think you understood what I meant.

Related

Best approach to instantiate object based on string

I'd like to discuss about the best approach (in C#) to instantiate an object based on an input string. Let me explain.
Let'say I have a base class:
public abstract class BaseCar
{
public asbtract int GetEngineID();
//Other stuff...
}
Then I have several implementations of this class, let's say:
public class SportCar : BaseCar
{
public override int GetEngine()
{
//Specific implementation
}
}
public class OtherCar: BaseCar
{
public override int GetEngine()
{
//Specific implementation
}
}
And so on...
What I'd like to do is to make a static CarFactory class which has a CreateCar method which accepts a string as a parameter and returns a BaseCar instance, depending on what string you give. The string would be a name of a child class.
For example, if I call CarFactory.CreateCar('SportCar') it should return a SportCar instance.
I know I could use a simple switch statement to check which car has been requested and create a new instance based on that but I don't like this approach for two reasons:
I plan to have a lot of child classes, hard-coding every case wouldn't be too easy to mantain
I plan to implement an inizialization procedure to also give some initial values to the objects I create (using Reflection), so mixing hard-coding and reflection doesn't seem to be a good idea for me.
What I was thinking about is to use the Assembly.CreateInstance from System.Reflection to create an instance of the specified class but since this is the first time I approach this problem, I don't know if there are better ways to do that. Is this a valid approach ?
Considering the input string will come from an XML file, is there a simplier method ? Maybe my issue is already handled in some .NET Assembly which I'm missing.
Here is what I came up with. A generic factory class that automatically registers all types that are a subclass of the given type, and allows you to instantiate them via their name. This is somewhat related to the approach shown in the Java SO question linked by #Achilles in the comments, only that there is no initialisation function associated with the type.
There is no need to maintain an enum/switch combination of all types. It should also be somewhat easily extendable to handle your proposed reflection based initialisation.
static class StringFactory<T> where T : class
{
static private Dictionary<string, Type> s_dKnownTypes = new Dictionary<string, Type>();
static StringFactory()
{
RegisterAll();
}
static private void RegisterAll()
{
var baseType = typeof(T);
foreach (var domainAssembly in AppDomain.CurrentDomain.GetAssemblies())
{
foreach (var type in domainAssembly.GetTypes()
.Where(t => t.IsSubclassOf(baseType)))
{
s_dKnownTypes.Add(type.Name, type);
}
}
}
static public T Create(string _sTypeName)
{
Type knownType;
if (s_dKnownTypes.TryGetValue(_sTypeName, out knownType))
{
return (T)Activator.CreateInstance(knownType);
}
throw new KeyNotFoundException();
}
}
Assuming the classes of your question exist, you would instantiate a specific car like this:
var car = StringFactory<BaseCar>.Create("SportsCar");
DoSomethingWith(car.EngineID());
Since your question was for a discussion about the best approaches, please consider this only one of them. I have not used this in a production environment, and it is entirely possible that it is the wrong approach to your specific situation. It works well enough to show the general principle, however, and should provide a starting point for further discussion.

Can I create an object in one function and constructing in another?

So I got an assignment [college student] to create a program that runs a garage. I have a class for every car type [FuelMotorcycle, ElectricMotorcycle, FuelCar, ElectricCar, etc.], each car type has its own constructor and they all differ from one another.
One of the assignment requirements is to "place the code that creates car objects [new], and this code alone, in a class on the logical part of the program, this code part cannot turn to the user directly or indirectly" (translated).
So the way I see it, I have a class, let's say "EmptyCarCreator" , that will have methods such as:
public static FuelMotorcycle CreateNewFuelMotorcycle()
{
FuelMotorcycle EmptyFuelMotorcycle;
return EmptyFuelMotorcycle;
}
obviously this won't compile, and even if it did, I couldn't use the "FuelMotorcycle" class constructor after I get it returned.
I need the user to input the elements for the constructor.
So, is there any other way to do this? I feel like I am missing something very basic here.
Please excuse any English errors, hope my question was clear.
You would need something like this:
public static class EmptyCarCreator
{
public static T Create<T>() where T : class, new()
{
return new T();
}
}
Then you would use it like this:
FuelMotorcycle myVehicle = EmptyCarCreator.Create<FuelMotorcycle>();
This will create a new class through the parameterless constructor.
There are other options that might be able to handle parameters a little better like this:
public static class EmptyCarCreator
{
public static object Create(Type type)
{
return Activator.CreateInstance(type);
}
}
To use this you would have to cast this returned object.
FuelMotorcycle myVehicle = (FuelMotorcycle)EmptyCarCreator.Create(typeof(FuelMotorcycle));

C# Calling generic method for each field of class

I have a data class with several members
public interface IEquipmentHolder
{
ITypedServiceProvider<IGrabberChannel> VideoChannels { get; }
ITypedServiceProvider<IMicrophone> Microphones { get; }
ITypedServiceProvider<ISpeaker> Speakers { get; }
...
}
and a function
void visitChilds<T>(ITypedServiceProvider<T> childsList) where T : INamedComponent
{
...
}
In some place of my code, I want call the function for each field of the data class. So i do:
visitChilds(equipment.VideoChannels);
visitChilds(equipment.Microphones);
...
But, probably I am going to add some new fields in the data class and don't want to forget to fix these place after that.
My question: is it possible to to call generic function for each data member of the class using reflection? if it is not, can we put compile time check for new fields in the c# code?
How often are you going to add more fields and 'forget' to update calling code?
How fast are you going to find out that you've forgotten to add a call to visitChilds()?
How about IEquipmentHolder has only one property ITypedServiceProvider<INamedComponent> Items { get; }?
Reflection is slower than direct calls (maybe you should emit IL?) and the additional code may be just not worth the 'improvement', especially if it will be easy to spot that new set it not visited.
Also consider, that adding a new set of INamedComponents requires a breaking change to IEquipmentHolder interface and all implementations.
You could use the Expression framework to generate a lambda that will call visitChilds for each property on the interface.
You'd need to use reflection to generate the expression, but this would be a one off hit. After that you'd have a dynamically compiled lambda you could call that would be a lot quicker.
I've done something similiar before whereby I convert an instance of an object into a Dictionary<string,object> where each key is the name of a property and the value is the value of the property. We generated a lambda for each type we wanted to convert, and it worked really well.
If ITypedServiceProvider is covariant, i.e., declared like this,
ITypedServiceProvider<out T>
{
...
}
then you could have
IEquipmentHolder
{
IEnumerable<ITypedServiceProvider<INamedComponent>>
NamedComponents { get; }
}
then your could do
void VisitChildren(IEquipmentHolder equipment)
{
foreach(var provider in equipment.NamedComponents)
{
provider.SomeMemberOfITypedServiceProvider();
}
}

Using pluralised table names with C# generics in MVC

I'm trying to create a generic function that will be used to access multiple tables in my database. Is there a way to used pluralised (pluralized for the non-British!) table names with my generic function.
I may be thinking about this the wrong way (fairly new to generics/templates), but here's my code (Db is just a global var for access to my database):
public void UpdateMyTables<TEntity>() {
// string plural = EntityObject<TEntity>.GetTableName(); // OR SOMETHING SIMILAR??
IEnumerable<EntityType> entitiesToUpdate = Db.<TEntity>; // Obviously doesn't work because TEntity is not a table name, it's an object type
foreach(<TEntity> e in entitiesToUpdate) {
e.MyColumn = "A string that I'm updating all these fields with";
}
}
So my question is: do I need to do some hackery to get the pluralised table name, or is there a function designed to return this (like GetTableName), or should I come at this from a different angle?
I also found a link that would help with the manual conversion here: Pluralising in mvc
Hugs and kisses and thanks in advance...
You can use the .Set() method to get the IEnumerable:
IEnumerable<TEntity> entitiesToUpdate = Db.Set<TEntity>();
To get the Table Name you could possibly use the code from this blog post or this SO answer.
The foreach should be written:
foreach(TEntity e in entitiesToUpdate) { // you can use "var" here if you prefer
e.MyColumn = "A string that I'm updating all these fields with";
}
Now, the problem is that TEntity does not have a .MyColumn property. If you are using this method with entities that inherit from a base class (called for example BaseEntity), which has that property, you can change the method declaration like this:
public void UpdateMyTables<TEntity>() where TEntity : BaseEntity {
This limits you to pass to call this method only with Entities that inherits from BaseEntity, but will give you access to the public properties and methods defined in BaseEntity.
To make the code above work, Base Entity should be declared like this:
public class BaseEntity { //of course it can be abstract or an interface...
public string MyColumn { get; set; }
}
I hope I understood what you wanted to do. If you need further information let us know. :)

Get a List of Generic Types Applied to Any Class

I have a particular need which I cannot seem to figure out. I've done some research into this, but cannot find a feasible solution.
I have a base class:
public abstract class BaseProvider<T> {}
this class in turn is inherited by two different provider classes:
public sealed class MonkeyProvider<T>
: BaseProvider<MonkeyProvider<T>>
where T
: IAnimalProvider
Within in the interface IAnimalProvider I expose a single property that all implementations must derive off. Now, MonkeyProvider and maybe DonkeyProvider or something similar needs to know what the assigned value for the property the root instance is:
public class JoburgZoo
: IAnimalProvider
{
#region IAnimalProvider members
public string Id{ get; set; }
#endregion
}
// somewhere in a console application
public static void Main(string[] args)
{
JoburgZoo zoo = new JoburgZoo();
zoo.Id = "Mammals";
**// edit: an instance of the provider will be created**
MonkeyProvider<JoburgZoo> mp = new MonkeyProvider<JoburgZoo>();
mp.CheckMonkeys(zoo); // where CheckMonkeys(JoburgZoo) is a method in the provider
}
Now, here is my actual question:
I have the need to expose an internal property through BaseProvider which every instance that implement it, has access to. This property needs to return the value of "Id" at any given point, but I cannot seem to be able get the value through reflection (which I know is the solution to this).
From my various fruitless efforts:
Type type = typeof(T); // this returns BaseProvider<MonkeyProvider<T>>
var generic = type.GetGenericTypeDefinition(); // brings back BaseProvider<T>
I can't create a new instance of T as it will clear all values currently assigned to the object. I can't iterate the property info collection, as that will only return the properties of BaseProvider.
Thanks for any help on this.
Eric
// Edit.
Added an additional call in the console main code above. the instance of MonkeyProvider<T> templates JoburgZoo, so in ProviderBase<T> it will look something like:
ProviderBase<MonkeyProvider<JoburgZoo>>
I want to know what the properties of JoburgZoo is, from within the BaseProvider<T> without the need to identify the object withing MonkeyProvider<T>.
Hope this makes sense.
With following class definition,
class BaseProvider<T>
{
//...
}
following code returns System.Int32 :
Type type = typeof(BaseProvider<Int32>);
foreach (var arg in type.GetGenericArguments())
{
MessageBox.Show(arg.FullName);
}

Categories

Resources