Create model in C# for TS Index Signatures object - c#

My angular fronend sending to .net core contoler object with index signature object.
Something like
export interface LazyLoadEvent {
first?: number;
rows?: number;
filters?: {
[s: string]: FilterMetadata;
};
}
export interface FilterMetadata {
value?: any;
matchMode?: string;
operator?: string;
}
I am trying create models in C# for request like this.
I am confused how I construct property filter in C# ?
What would be the equivalent of TS Index Signatures implantation in C# ?
From typescriptlang
Index Signatures
Sometimes you don’t know all the names of a type’s properties ahead of time, but you do know the shape of the values.
In those cases you can use an index signature to describe the types of possible values

You could use a Dictionary
Dictionary<string, FilterMetadata> Filters { get; set; }
Which you can access using the indexer access
var value = Filters["SomeKey"];
or by using the TryGetValue method.

Related

Using a Dictionary<string, Type> to use the value as type of a list

I am trying to build a solution fitting with the problem of not knowing what kind of Setting type I am dealing with.
I got a Dictionary<string, Type> (which I initially wanted to make <string, class> but that didn't work)
that I want to fill with the setting code and the type of class attached to it i.e.
{ "person_customField", typeof(CustomFieldModel) }
Why I want to do this is because I have a field in my database filled with json data that should be deserialized to a List<> but I don't know what kind of setting it is until I get the object from the database. I can use the Code field to detemine what type it is (person_CustomField should use the CustomFieldModel class, but emailSetting should use EmailSettingModel to match parameters to.
Is there a way to successfully make this statement work with?
JsonConvert.DeserializeObject<List<SettingTypes[record.SettingCode]>>(record.SettingValues).ToList<ISetting>()
Or should I go a different route
Code Sample:
public static readonly Dictionary<string, Type> SettingTypes = new Dictionary<string, Type>()
{
{ "person_CustomFields", typeof(CustomFieldModel)},
};
public static TenantSettingEdit ConvertToTenantSettingEdit(this T_TenantSetting rec)
{
var test = SettingTypes[rec.TENS_Code];
TenantSettingEdit item = new TenantSettingEdit()
{
IDToken = rec.TENS_TenantSettingID.toVirtualGuid().ToString(),
Code = rec.TENS_Code,
Settings = JsonConvert.DeserializeObject<List<SettingTypes[rec.TENS_Code]>>(rec.TENS_Setting).ToList<ITenantSetting>(),
IsActive = rec.TENS_ActiveRec,
};
return item;
}
(I have done this before with PHP but I am not sure if this is even remotely possible with C#)
Why I want to do this is because I have a field in my database filled
with json data that should be deserialized to a List<> but I don't
know what kind of setting it is until I get the object from the
database.
If you're using Json.Net for JSON serialization/deserialization you can use the TypeNameHandling property to embed Type information in the resulting JSON. That JSON can the be deserialized by Json.Net without additional information. If it is necessary to map custom values to the types instead of the automatically generated ones you can use a SerializationBinder (check out this answer).
If none of those help you, you can still fall back to reflection in the way M Kloster describes.
You cannot use a variable as the type parameter in the code, no. What you need to do is to generate the type-specific method by reflection:
var genericMethod = ((Func<string, int>)Json.DeserializeObject<int>).Method.GetGenericMethodDefinition();
var boundMethod = genericMethod.MakeGenericMethod(SettingTypes[record.SettingCode]);
var result = boundMethod.Invoke(null, rec.TENS_Setting)...

How to pass variable entities to a generic function?

If i generate my entities through Entity Framework Database First, and i want to use a function like that:
AuditManager.DefaultConfiguration.Exclude<T>();
considering that the number of times i want to call it should be equal to the number of entities
ex:
AuditManager.DefaultConfiguration.Exclude<Employee>();
AuditManager.DefaultConfiguration.Exclude<Department>();
AuditManager.DefaultConfiguration.Exclude<Room>();
Now how to Loop through selected number of entities and pass every one to the Exclude function ?
The obvious solution would be to call the method for every entity-type you want to hide. Like this:
AuditManager.DefaultConfiguration.Exclude<Employee>();
AuditManager.DefaultConfiguration.Exclude<Department>();
AuditManager.DefaultConfiguration.Exclude<Room>();
You can add conditional statements (ifs) around them to do it dynamically.
Howevery, if you want a fully flexible solution, where you call the Exclude method based on metadata, you need something else. Something like this:
var types = new[] { typeof(Employee), typeof(Department), typeof(Room) };
var instance = AuditManager.DefaultConfiguration;
var openGenericMethod = instance.GetType().GetMethod("Exclude");
foreach (var #type in types)
{
var closedGenericMethod = openGenericMethod.MakeGenericMethod(#type);
closedGenericMethod.Invoke(instance, null);
}
This assumes that the Exclude<T> method is an instance method on whatever instance DefaultConfiguration points to.
An alternative to looping through your entity types is to make the entities you don't want audited implement the same interface and exclude that. For example:
public interface IExcludeFromAudit
{ }
And your entities:
public class Order : IExcludeFromAudit
{
//snip
}
And now just exclude the interface:
AuditManager.DefaultConfiguration.Exclude<IExcludeFromAudit>();
The benefit of this is that it's now easy to control which ones are excluded.

Determine needed class dynamically

I have several external devices which I can communicate to via a common API.
string busIdentifier = "BUS:0:1";
var dev = new CommonDeviceDriver(busIdentifier);
Now I can query the device:
string identifier = dev.QueryIdentifier();
Now I have several concrete driver for example ConcreteDeviceA, ConcreteDeviceB and ConcreteDeviceC. Each of the device driver should have an ìdentifier`.
Now I want to load the right device driver for this previously queried identifer.
How to to that in C#?
Coming from python I would do something like that:
# Have a dictionary where key is identifier and value is the class
supported_devices = {ConcreteDeviceA.identifer : ConcreteDeviceA,
ConcreteDeviceB.identifer : ConcreteDeviceB,
ConcreteDeviceC.identifer : ConcreteDeviceC}
busIdentifier = "BUS:0:1"
dev = CommonDeviceDriver(busIdentifier)
identifier = dev.QueryIdentifier()
concrete_device = supported_devices[identifier](dev) # Get class and call constructor
The simplest way to do this would be a factory method. If you know the available types at compile-time, then you can simply enumerate them in code.
public static DriverBase CreateDriver(string identifier, object device) {
switch (identifier) {
case IDENTIFIER_A: return new ConcreteDeviceA(device);
// etc
}
}
If you don't know all of the types at compile time (or you really object to the above usage), then you can use reflection. Then you can essentially have a dictionary mapping identifier to type (as you have in Python), and instantiate the object either using Activator.CreateInstance, or by looking up its constructor yourself. In that case, you'll have to cast the return object to the base type.

Deep Reflection in .NET

I need to create the ability to drill through an objects properties like two or three deep. For instance, class A has a property reference to class B, which I need to access class C. What is the best way to do this: straight reflection, or maybe using the TypeDescriptor, or something else?
Thanks.
It's not too hard to write. I put a few classes together to deal with this so I could serialize properties of a WinForm. Take a look at this class and the related classes.
http://csharptest.net/browse/src/Library/Reflection/PropertySerializer.cs
If you know the path in a static context (ie the path is always the same) and the properties are accessible (internal or public) you can use dynamic
[Test]
public void Foo()
{
var a = new A
{
B = new B
{
C = new C
{
Name = "hello"
}
}
};
DoReflection(a);
}
private void DoReflection(dynamic value)
{
string message = value.B.C.Name;
Debug.WriteLine(message);
}
I you wanna write you own serialization code for whatever reason, you'll be using reflection.
What you do is that you write a recursive method of serlizating a type. You then apply this as you see fit to get the result.
var type = myObjectOfSomeType.GetType();
// now depending on what you want to store
// I'll save all public properties
var properties = type.GetProperties(); // get all public properties
foreach(var p in properties)
{
var value = p.GetValue(myObjectOfSomeType, null);
Writevalue(p.Name, value);
}
The implementation of WriteValue have to recognize the built in types and treat them accordingly, that's typical things like string, char, integer, double, DateTime etc.
If it encounters a sequence or collection you need to write out many values.
If it encounters a non trivial type you'll apply this recursive pattern again.
The end result is a recursive algorithm that traverses your object model and writes out values as it encounters types that I know how to serialize.
However, I do recommend looking into WCF, not for building services, but for serialization. It shipped as part of the .NET 3.0 framework with a new assembly System.Runtime.Serilization and in general is very capable when dealing with serialization and data annotations.

How do I write a method that can output data from any class using generics?

I'm trying to write a custom method to populate a ListView control using Generics:
private void BindDataToListView(List<T> containerItems)
{
this.View = View.Details;
this.GridLines = true;
this.FullRowSelect = true;
if (this.Items.Count > 0)
this.Items.Clear();
this.BeginUpdate();
int i = 0;
foreach (T item in containerItems)
{
// do something
}
this.EndUpdate();
}
The parameter containerItems can have many items since I'm using generics. But I get stuck in the foreach loop. How do I access the values in containerItems?
Do I have to use reflection on each instance of T in the foreach loop? I think I do to retrieve the property name. But once I have the property name of the type T, how do I retrieve the value?
The most common way of doing this (with winforms) is via TypeDescriptor; this allow you to use things DataTable the same as classes; the "full" pattern is quite complex (and involves checking for IListSource, ITypedList, etc; however, the short version is; to get the available properties:
PropertyDescriptorCollection props = TypeDescriptor.GetProperties(typeof(T));
To get a named property:
PropertDescriptor prop = props[propName];
To get a value for an instance (sourceObject):
object val = prop.GetValue(sourceObject);
To render a value as a string (using the designated converter):
string s = prop.Converter.ConvertToString(val);
You could limit T to an interface, and use that interface in the iteration.
What does T represent ?
Like it is now, it is a generic type and it can be ... anything.
So, what I would do, is create an interface IListViewBindable or something like that. That interface could then have a method 'CreateListViewItem' for instance.
Then, I would change the method, so that a constraint is applied to your type-parameter T, saying that T should implement IListViewBindable, like this:
public void BindDataToListView<T>( List<T> containerItems ) where T : IListViewBindable
{}
In your BindDataToListView method, you could then do this:
foreach( T item in containerItems )
{
this.Items.Add (item.CreateListViewItem());
}
If the items in the list are of totally unconstrained type, then you can treat them as simply of type object. You call GetType() to get the type of the object. On that you can call GetProperties() to get an array of PropertyInfo objects. And on those you can call GetValue() to retrieve the value of the property.
If you already know the name of a property, just call GetProperty() to retrieve it:
string valueAsString = item.GetType().GetProperty("Something")
.GetValue(item, null).ToString();
I don't completely understand what you're asking, but I think that this will point you in the right direction. Please ask for clarification if it looks like it can help and it's unclear.
You can access a given property of an object using reflection via
object o;
PropertyInfo info = o.GetType().GetProperty().GetProperty("NameOfPropertyIWant");
and you can get the value via
object value = info.GetValue(o, null);
Now, if you're going to be accessing a property of the same name on objects of various types, you should consider adding an interface
public interface IHasThePropertyIWant {
object NameOfPropertyIWant { get; }
}
Then you can enforce this via
void BindDataToListView(List<T> containerItems) where T : IHasThePropertyIWant
and use it in the look like so
foreach (T item in containerItems) {
object o = item.NameOfPropertyIWant;
// do something with o
}
ObjectListView uses reflection to do exactly what you are trying to do: populate a ListView using reflection. You could save yourself a lot of trouble by using it. It has already solved all the tricky problems you are going to encounter on this path.
If you really, really want to do it yourself, Marc's answer is (of course) completely correct.

Categories

Resources