Consider a situation:
I have a method which use DataRow:
public void MyMethod (DataRow input)
{
DoSomething(input["Name1"]);
}
But now I have some another input types with indexer which I want to pass to this method. St like:
public void MyMethod (AnyTypeWithIndexer input)
{
DoSomething(input["Name1"]);
}
But I haven't found anything like that. I tried IDictionary but it didn't work.
Is there any super type st like "Indexable" or anything with which I can replace the "AnyTypeWithIndexer"?
Note: I still need this method to pass the DataRow and also my custom class (which I want to implement).
Can anybody help?
Thanks.
No, unfortunately, there is no interface that automatically applies to "all classes with an indexer that takes a string argument and returns an object".
What you can do, however, is to create a "proxy class" that implements such an interface
yourself:
public interface IStringToObjectIndexable
{
object this[string index] { get; set; }
}
class DataRowWrapper : IStringToObjectIndexable
{
private readonly DataRow row;
public DataRowWrapper(DataRow row) => this.row = row;
public object this[string index]
{
get => row[index];
set => row[index] = value;
}
}
MyMethod can now be declared as follows:
public void MyMethod(IStringToObjectIndexable input)
{
DoSomething(input["Name1"]);
}
// Compatibility overload
public void MyMethod(DataRow input) => MyMethod(new DataRowWrapper(input));
You can use dynamic type, but you will need to be noticed about the disadvantages of dynamic, such as performance drawbacks because of DLR, and the fact that type safety should be on your shoulders
public class WithIndexer
{
public int this[string key] => 42;
}
public static async Task Main()
{
Dictionary<string, int> a = new Dictionary<string, int>();
a.Add("meow", 41);
Foo(a, "meow");
Foo(new WithIndexer(), "key");
}
private static void Foo(dynamic indexed, string key)
{
Console.WriteLine(indexed[key]);
}
Output:
41
42
Related
How can I convert these two ConvertDtoListToAddresses and ConvertDtoListToDocuments C# methods to a generic? I've tried passing in two generic type variables, but when I get down to 'Add' in the loop I get stuck on various errors. Converting from a DTO to its respective DBO is done in the constructor of the DBO, which I think is part of the problem.
private void ConvertDtoToPerson(PersonDTO dto)
{
Id = dto.Id;
Fname = dto.FirstName;
Mname = dto.MiddleName;
Lname = dto.LastName;
Suffix = dto.Suffix;
Maiden = dto.MaidenName;
Addresses = ConvertDtoListToAddresses(dto.AddressesDto); // want to convert to generic
Documents = ConvertDtoListToDocuments(dto.DocumentsDto); // want to convert to generic
}
private static ICollection<Address>? ConvertDtoListToAddresses(ICollection<AddressDTO>? addressesDto)
{
if (addressesDto is not null && addressesDto.Any())
{
ICollection<Address> addys = new List<Address>();
foreach (AddressDTO dto in addressesDto)
{
// Converts from dto in constructor
addys.Add(new Address(dto));
}
return addys;
}
return null;
}
private static ICollection<Document>? ConvertDtoListToDocuments(ICollection<DocumentDTO>? documentsDto)
{
if (documentsDto is not null && documentsDto.Any())
{
ICollection<Document> docs = new List<Document>();
foreach (DocumentDTO dto in documentsDto)
{
// Converts from dto in constructor
docs.Add(new Document(dto));
}
return docs;
}
return null;
}
Here is what I tried:
Addresses = ConvertDtoListToType<Address, AddressDTO>(dto.AddressesDto);
private static ICollection<T>? ConvertDtoListToType<T, D>(ICollection<D>? dtoCollection)
{
if (dtoCollection is not null && dtoCollection.Any())
{
ICollection<T> tList = new List<T>();
foreach (D dto in dtoCollection)
{
tList.Add(new T(dto)); // <-- This is where I'm having trouble
}
return tList;
}
return null;
}
Use of a Func<D, T> factory parameter would sort this out.
private static ICollection<T>? ConvertDtoListToType<T, D>(ICollection<D>? dtoCollection, Func<D, T> factory)
{
if (dtoCollection is not null && dtoCollection.Any())
{
ICollection<T> tList = new List<T>();
foreach (D dto in dtoCollection)
{
tList.Add(factory(dto));
}
return tList;
}
return null;
}
Do keep in mind that that is almost the semantic equivalent of this:
private static ICollection<T>? ConvertDtoListToType<T, D>(ICollection<D>? dtoCollection, Func<D, T> factory)
=> dtoCollection?.Select(d => factory(d))?.ToList();
I'd question the idea that an empty dtoCollection should return a null final collection anyway. This is probably a better implementation.
So, having said that, your original method offers very little functionality benefit. It's code for code's sake. A simple Select/ToList pair keeps your code simple.
In any case, you can provide a static method off of Address and Document to provide the Func<D, T> that you need.
public class Address
{
AddressDTO dto;
public static Address CreateFromDto(AddressDTO dto)
=> new Address(dto);
public Address(AddressDTO dto)
{
this.dto = dto;
}
}
Now, calling it is like this:
var addresses = ConvertDtoListToType(addressDtos, Address.CreateFromDto);
Or:
var addresses = addressDtos?.Select(Address.CreateFromDto)?.ToList();
What you need is to be able to provide a constraint on the Type T to say that it has a constructor that takes a parameter of type D. Something like this:
private static ICollection<T>? ConvertDtoListToType<T, D>(
ICollection<D>? dtoCollection) where T : new(D)
{}
But this does not exist in C#. The workaround is to provide a factory method to create your type T given a type D. i.e. Something like:
private static ICollection<T>? ConvertDtoListToType<T, D>(
ICollection<D>? dtoCollection, Func<D, T> factory)
{
// Use factory(dto), instead of new T(dto)
}
But as #Zee says, you should have a look at Automapper, which can convert between types of collections.
I have 2 dictionaries. How I can assign DerivedClass dictionary to DerivedClass dictionary ?
Below code not worrking?
How can I change it?
public class BaseClass
{
public void DoWork() { }
public int WorkField;
public int WorkProperty
{
get { return 0; }
}
}
public class DerivedClass : BaseClass
{
public new void DoWork() { }
public new int WorkField;
public new int WorkProperty
{
get { return 0; }
}
}
class Program
{
static void Main(string[] args)
{
var derivedclass = new Dictionary<string, DerivedClass>();
var baseClass = new Dictionary<string, BaseClass>();
Dictionary<string, BaseClass> AAA = derivedclass;
Console.ReadKey();
}
}
You can't cast the dictionary directly, but you can create a new dictionary, something like this will work:
Dictionary<string, BaseClass> AAA =
derivedclass.ToDictionary(
k => k.Key,
v => (BaseClass)v.Value);
You can't. Dictionary (along with all classes in C#) are invariant with respect their generic arguments.
And even if C# worked to support generic type variance on classes (rather than just interfaces and delegates) Dictionary is conceptually not invariant with respect to the type of the value of the dictionary. You can add new values to a dictionary, so if you could cast a Dictionary<int, Tiger> to a Dictionary<int, Animal> then you could put a Chicken in that dictionary of tigers, and we all know how well that would end.
If you had an IReadOnlyDictionary interface it could potentially be covariant with respect to the type of the value, although the .NET implementation isn't.
how do i get a list of all fields within all nested classes
class AirCraft
{
class fighterJets
{
public string forSeas = "fj_f18";
public string ForLand = "fj_f15";
}
class helicopters
{
public string openFields = "Apachi";
public string CloseCombat = "Cobra";
}
}
the code i am trying to use is from one of the posts here
i can break this into two or three separeted lines of code and it will work
the question is about the expression , and using shortest/modern code.
IEnumerable<FieldInfo> GetAllFields(Type type) {
return type.GetNestedTypes().SelectMany(GetAllFields)
.Concat(type.GetFields());
}
this will return fieldInfo not the names or values,
and i need it more as a list of string or better a dictionary for both fields-values and names
but a list will do for now.
List<string> (or dictionary) ChosenContainersNamesOrValuesOfAllNested(Type T)
{
return a shortest syntax for that task, using lambda rather foreach
}
thanks.
You can just use Linq's Select extension method to get just the names:
IEnumerable<string> GetAllFieldNames(Type type)
{
// uses your existing method
return GetAllFields(type).Select(f => f.Name);
}
Or the ToDictionary extension method to construct a dictionary:
IDictionary<string, object> GetAllFieldNamesAndValues(object instance)
{
return instance.GetType()
.GetFields()
.ToDictionary(f => f.Name, f => f.GetValue(instance));
}
Note you will need an instance of the type to get the values. Also, this will only work for a single type, since you will need an instance of each type to get the values.
However, if you defined your fields as static you could do this:
class AirCraft
{
public class fighterJets
{
public static string forSeas = "fj_f18";
public static string ForLand = "fj_f15";
}
public class helicopters
{
public static string openFields = "Apachi";
public static string CloseCombat = "Cobra";
}
}
IEnumerable<FieldInfo> GetAllStaticFields(Type type)
{
return type.GetNestedTypes().SelectMany(GetAllFields)
.Concat(type.GetFields(BindingFlags.Public | BindingFlags.Static));
}
IDictionary<string, object> GetAllStaticFieldNamesAndValues(Type type)
{
return GetAllStaticFields(type)
.ToDictionary(f => f.Name, f => f.GetValue(null));
}
This works because static fields are not bound to any instance of the class.
I've started using C# Expression constructs, and I've got a question about how generics are applied in the following situation:
Consider I have a type MyObject which is a base class for many different types. Inside this class I have the following code:
// This is a String Indexer Expression, used to define the string indexer when the object is in a collection of MyObjects
public Expression<Func<MyObject, string, bool>> StringIndexExpression { get; private set;}
// I use this method in Set StringIndexExpression and T is a subtype of MyObject
protected void DefineStringIndexer<T>(Expression<T, string, bool>> expresson) where T : MyObject
{
StringIndexExpression = expression;
}
This is how I use DefineStringIndexer:
public class MyBusinessObject : MyObject
{
public string Name { get; set; }
public MyBusinessObject()
{
Name = "Test";
DefineStringIndexer<MyBusinessObject>((item, value) => item.Name == value);
}
}
However in the assignment inside DefineStringIndexer I get the compile error:
Cannot implicitly convert type
System.Linq.Expression.Expression< MyObject, string, bool > to
System.Linq.Expression.Expression < MyBusinessObject, string, bool >>
Can I use Generics with C# Expressions in this situation? I want to use T in DefineStringIndexer so I can avoid casting MyObject inside the lambda.
The assignment will not work, because the Func<MyBusinessObject,string,bool> type is not assignment-compatible with Func<MyObject,string,bool>. However, the parameters of the two functors are compatible, so you can add a wrapper to make it work:
protected void DefineStringIndexer<T>(Func<T,string,bool> expresson) where T : MyObject {
StringIndexExpression = (t,s) => expression(t, s);
}
Would this work better for you?
Edit: Added <T> to constraint - think you will need that :)
class MyObject<T>
{
// This is a String Indexer Expression, used to define the string indexer when the object is in a collection of MyObjects
public Expression<Func<T, string, bool>> StringIndexExpression { get; private set;}
// I use this method in Set StringIndexExpression and T is a subtype of MyObject
protected void DefineStringIndexer<T>(Expression<T, string, bool>> expresson)
where T : MyObject<T> // Think you need this constraint to also have the generic param
{
StringIndexExpression = expression;
}
}
then:
public class MyBusinessObject : MyObject<MyBusinessObject>
{
public string Name { get; set; }
public MyBusinessObject()
{
Name = "Test";
DefineStringIndexer<MyBusinessObject>((item, value) => item.Name == value);
}
}
I guess I've seen it somewhere before, but now I can't remember nor find it. Is there a way to make a getter property with arguments?
I mean, as I can convert "float getSize();" to "float Size":
float getSize() {
return this.size;
}
float Size {
get { return this.size; }
}
Then, could I convert, for example, "float getSize(String unit);" to "float Size(String unit)" or something like that?
float getSize(String unit) {
return this.size;
}
float Size(String unit) {
get {
if (unit == Unit.Meters)
return this.size/100;
else
return this.size;
}
}
I think there's no really problem of using function at all, but may look better this way :P
To answer the question: No, it is not possible, and as already pointed out, a getter with a parameter would look just like a method.
The thing you are thinking about might be an indexed default property, which looks like this:
class Test
{
public string this[int index]
{
get { return index.ToString(); }
}
}
This allows you to index into an instance of Test, like this:
Test t = new Test();
string value = t[1];
Interestingly, having a property with parameter is possible in VB.NET, like this:
Public ReadOnly Property oPair(param As String) As Result
Get
'some code depends on param
End Get
End Property
It's not superior to a regular function, but sometimes it is nice to have such a possibility.
I know this is an old post, but I ran into wanting to do this today in C#. Whether that's a good thing or not is probably falling on the 'not' side. However, I ran across an interesting idea posted by Mark Jones at (https://social.msdn.microsoft.com/forums/en-US/5a25bc83-990e-4657-aa9c-69bca5158d48/overloaded-c-properties-with-arguments?prof=required), but I didn't quite like the feel of it.
So I wrote my own based on his (mine is in .Net 5.0 with Nullable = enable):
class ParameterizedProperty<T>
{
private readonly Func<int, T> getter;
private readonly Action<int, T> setter;
public T this[int index]
{
get => this.getter(index);
set => this.setter(index, value);
}
public ParameterizedProperty(Func<int, T> getter, Action<int, T> setter)
{
this.getter = getter;
this.setter = setter;
}
}
class NamedParameterizedProperty<T>
{
private readonly Func<int, T> indexedGetter;
private readonly Action<int, T> indexedSetter;
private readonly Func<string, T> namedGetter;
private readonly Action<string, T> namedSetter;
public T this[int index]
{
get => this.indexedGetter(index);
set => this.indexedSetter(index, value);
}
public T this[string name]
{
get => this.namedGetter(name);
set => this.namedSetter(name, value);
}
public NamedParameterizedProperty(Func<int, T> indexedGetter, Action<int, T> indexedSetter, Func<string, T> namedGetter, Action<string, T> namedSetter)
{
this.indexedGetter = indexedGetter;
this.indexedSetter = indexedSetter;
this.namedGetter = namedGetter;
this.namedSetter = namedSetter;
}
}
class ReadOnlyParameterizedProperty<T>
{
private readonly Func<int, T> getter;
public T this[int index] => this.getter(index);
public ReadOnlyParameterizedProperty(Func<int, T> getter)
{
this.getter = getter;
}
}
class ReadOnlyNamedParameterizedProperty<T>
{
private readonly Func<int, T> indexedGetter;
private readonly Func<string, T> namedGetter;
public T this[int index] => this.indexedGetter(index);
public T this[string name] => this.namedGetter(name);
public ReadOnlyNamedParameterizedProperty(Func<int, T> indexedGetter, Func<string, T> namedGetter)
{
this.indexedGetter = indexedGetter;
this.namedGetter = namedGetter;
}
}
So a little about my solution: I opted for Func<> & Action<> for the getters/setters because I didn't want this helper class to have to need any knowledge of underlying property it would be supporting. Instead, the class that owns the property would have public (or private) methods for get_X / set_X (or whatever naming convention you wish to use) that would handle everything - such as validation.
Now as to my use case for this: I had a class that has an internal array of a specific type. I have a default indexer property public primaryType this[int index], but it has a couple of other types that it understands and can convert to / from for primaryType. However, I can't do public otherType this[int index], and I didn't really want to do public methods called something like 'get_OtherType` & 'set_OtherType'.
These helper classes let me do something like:
public ParameterizedProperty<OtherType> OtherType { get; }
public MyClass()
{
this.OtherType = new(get_OtherType, set_OtherType);
}
private OtherType get_OtherType(int index)
{
/* validate index, convert PrimaryType at index to OtherType and return. */
}
private void set_OtherType(int index, OtherType value)
{
/* validate index, validate value, convert to PrimaryType and set to internal array. */
}
Then in other classes / UIs that use this class, where 'OtherType' is more convenient for them to work with then 'PrimaryType', I can have them doing things like myClass1.OtherType[0] = otherType;, but if they work with the primary type, then they can do myClass1[0] = primaryType - or if I just want to be consistent / explicit, I don't have a default indexer property, and I use a ParameterizedProperty for the primary type as well, IE: myClass1.PrimaryType[0] = primaryType;
Again, whether this is a good idea to go this route or not, I'm unsure.
It is possible for a class object to reasonably-efficiently have something that behaves as a named indexed property getter by having a property return a struct which simply holds a private reference to the class object and includes an indexed property getter which chains to a method in the class. Such a single-item structure can be generated at basically no cost (it can likely fit in a register, and will be loaded with a value that's in another register; the JIT may even be able to recognize that the same register can be used for both purposes), so if using such a getter makes code more readable that's a substantial argument in favor.
Unfortunately, the inability of struct members to indicate whether or not they modify the underlying structure makes it impossible to use the same approach for an indexed property setter. Even though it would be helpful it one could have have an OrderedCollection<T> with something like:
struct ByIndexAccessor {
OrderedCollection<T> owner;
ByIndexAccessor(OrderedCollection<T> o) { owner = o; }
T this[int index] {
get { return owner.handleGet(index); }
set { owner.handleSet(index, value); }
}
}
ByIndexAccessor ByIndex {
get {return new ByIndexAccessor(this); }
}
and say myCollection.ByIndex[3] = newThing;, C# would reject such code because it has no way of knowing that this particular indexed set implementation can safely be used on a read-only structure.