Why an object saves properties when upcasted - c#

I've got a simple question concerning upcasting in c#. For example I have two interfaces:
interface IUSer
{
string UserName { get; set; }
}
interface IAdmin: IUSer
{
string Password { get; set; }
}
...and a class implementing IAdmin interface:
class Admin : IAdmin
{
public string Password { get; set; }
public string UserName { get; set; }
}
When I create an object of type Admin and try to upcast it to IUser, technically I can then only access UserName user.UserName:
var admin = new Admin() { UserName = "Arthur", Password = "hello" };
var user = (IUSer)admin;
Console.WriteLine( user.UserName );
...but If I cycle through this object's properties using Reflection, like that:
private static void Outputter(IUSer user)
{
foreach (var prop in user.GetType().GetProperties())
{
Console.WriteLine(prop.Name + " " + prop.GetValue(admin));
}
}
...I can also see Password property. The question is - why it is saved when upcasted?

The question is - why it is saved when upcasted?
Because casting doesn't change the object at all. It just changes how you're viewing the object.
Think of it like being a person. You may have different ways that people can view you:
A colleague
A manager
A family member
A friend
They only "see" certain aspects of you, but that doesn't change who you are.
Likewise a simple reference conversion doesn't change the object. If you call user.GetType() it will still report the actual type of the object. It's just that when you view the object through a particular lens (whether that's an interface or a base class) you only see the members that lens shows you.
(Note that a cast that calls a user-defined conversion, e.g. casting from XElement to string, is entirely different. That returns a reference to a new object, rather than just regarding the existing object in a different way.)
If you only want to see the IUser properties, use typeof(IUser).GetProperties() instead of calling GetType() first:
private static void Outputter(IUser user)
{
foreach (var prop in typeof(IUser).GetProperties())
{
Console.WriteLine($"{prop.Name}: {prop.GetValue(user)}");
}
}
Although I'm not sure it's particularly useful to do that with reflection in most cases.

when you cast the object of any type to their base type, you are just holding that object with they type of base.
object doesn't loos its properties by that.
If you see a simplest example : Use of non generic collection
when you add some object (let's say of Admin class) in ArrayList, you are actually converting that object into type object (Boxing) and then store it arraylist. So it is ultimate example of up-casting! How?
The object type is an alias for Object in the .NET Framework. In the unified type system of C#, all types, predefined and user-defined, reference types and value types, inherit directly or indirectly from Object.
Full Post
Now object type doesn't hold properties like userName password.
So when you try to access those property from the object you get directly from arraylist, you will not able to do so. Because current you are dealing with the type object and you will get access only those properties or members which is supported by object type (but here you are not getting access, still those properties are there). In addition as note in other answer GetType() method will surely return it's original type too.
But when you get that original object back from array list by casting it back to Admin type (Unboxing) , you will see those properties are there in your object as they were before. Only thing which is changed is, now you are able to access them because Admin type supports them.
Read this for more detail

Related

c# type of an object when using derived class

Having the following code:
class TrxBase
{
public string Prop1 { get; set; }
public string Prop2 { get; set; }
}
class Trx : TrxBase
{
public string Prop3 { get; set; }
}
static void Print(TrxBase trx)
{
if (trx is Trx trx1)
{
Console.WriteLine(trx1.Prop3);
}
else
{
Console.WriteLine("no match");
}
}
static void Main(string[] args)
{
Trx t = new Trx();
t.Prop1 = "prop 1";
t.Prop3 = "prop 3";
Print(t);
}
The code from above prints "prop 3". From what I knew. in the Print method, the object will be read as an TrxBase one. And if this is the case, where is the Prop3 property saved? How does the program knows that my parameter is actually an Trx object?
You need to distinguish between compile time types (those that e.g. determine which overload of a method to call) and runtime types (which are used by e.g. reflection). Whatever contortions you go through with a particular object1 (casting it to a base type, etc) doesn't change the runtime type of the object.
So just because you're passing t to Print which asks for a TrxBase, it doesn't change t into a TrxBase.
And if, inside Print, it tests for and determines that it's a Trx, it's perfectly valid for it to cast it back to that type (hidden inside the pattern matching syntax) and start treating it as the type it truly is (although, of course, it could be a type even more derived from Trx.
Bonus reading: Eric Lippert's Representation and Identity
1Provided you understand that reference-changing conversions give you a new object. This is also further explained in the bonus reading above.
This is how C# works, when you pass derived type object to a method with parameter with base type object compiler simply takes this derived object and interprets it like it is base.
In your case you are passing derived (Trx) object to method with TrxBase parameter. So now in the scope of Print(TrxBase trx) , trx will be treated like it is TrxBase, but then you are using pattern matching to determine if this trx can be reprsented into more derived Trx object type, which in your case is true, can and therefore prints prop 3.
It is possible to cast derived type to more base type, but the other way will result into InvalidCastException coming from CLR. Because if you think about it - lets say you allocate new object of type TrxBase, CLR allocator will allocate such object on the heap (or the stack if value type) with all the needed properties this object has. Now if you request from CLR to cast this specific object to something more specific you are ultimately requesting this specific memory layout to change into another (adding fields, properties and such from your specific object) which CLR does not support.

Reimplementing Dictionary<string, dynamic>

I want to implement a class that behaves similarly to a Dictionary<string, dynamic>, because the dynamic keyword is causing a weird exception caused by CAS issues which I cannot resolve somewhere else on the project. Basically I want a dictionary that allows getting and setting heterogeneous values without explicit casting.
My attempt has been to get an internal Dictionary<string, Tuple<Type, object>> with the intention of casting it correctly. I would like to overload the square-bracket operator for getting and setting. However, I cannot figure out the correct syntax to do this. I would like to do something like this:
class DynDictionary<T>
{
private Dictionary<string, Tuple<Type, object>> _dict = new Dictionary<string, Tuple<Type, object>>();
public T this[string key]
{
get { return (_dict[key].Item1)_dict[key].Item2; }
set { _dict[key] = new Tuple(typeof(value), value); }
}
}
which does not compile for several reasons, of course. However, I can't even make this work with a generic class, and I do not want a generic class because I will then have to specify the type when instantiating, which is exactly what I'm trying to avoid.
Is there a solution to this? Am I meddling into things I shouldn't touch?
No, there is no such option.
As you noted, for:
public T this[] { get; set; }
you need some "generic-ness" at the outer scope, as the this[] also can't be generic on its own. So, your class/whatever would be generic-<T> and force the users not only to specify the T, but also to specify only one single T for all elements.
For Dictionary<string, Tuple<Type, object>> the best you can have is:
public object this[] { get; set; }
public IMyInterface this[] { get; set; }
this is because at the time of compilation, your whole dictionary-class does not have any information about the item types. The code is limited to object as in Typle<Type,object>. The only things you can do is to return an object, or try to cast it to some other known type, like interface.
If you resign from using a this[], you can try to make a 'smart getter':
public TValue GetItem<TValue>(TKey index) { ... }
public void SetItem<TValue>(TKey index, TValue value) { ... }
which would just do all the casting (like return (TValue)tuple.Item2). However, that would have some issues like difficult usage when used in context when "TValue" is unknown. So, you'd also probably need
public object GetItem(TKey index) { ... }
public void SetItem(TKey index, object value) { ... }
just to avoid cumbersome GetItem<object>. Of course, wherever the TValue versions are used, the user would need to specify the TValue explicitely (except for the SetValue where it'd be probably inferred, not necessarily correctly).
Now, let's get back to basics. What is your idea about
public T this[] { get; set; }
anyways, hm? As you bundle together the Type and Object in the Tuple, it seems like you want to be able to pack a heterogenous items into the Dictionary, right? So, tell me, how the final user and/or how the code/compiler would be able to guess wnat is being returned:
var foo = myDictionary["bar"];
what would be the type of the foo variable? Compiler can't guess, because at compilation myDictionary only know it will hold some Tuple<Type,object> but it does not hold anything now. Also, it actually does not even exist yet, since it's being compiled.. It is simply not possible to force a 'return value' to be "typed" with the exact type taken from your Tuple.
Also, why do you even carry the Type in that Tuple? The object kept in the dictionary knows its Type, always. You don't need to carry the Type for it, you can simply .GetType() on that object with just the same effect. If you'd want to preserve upcasted type information (example: have a Bar inherited from Foo, upcast Bar as Foo and put into magiccontainer, retrieve back as Foo not Bar), then you are a bit out of luck.. Even dynamic would not help with that and would return you "dynamic object" which would know itself to be "Bar" and which would allow you to dynamically call all Bar methods. I think that carrying the Type is completely unnecessary, unless you have some strong shielding/isolation requirements - but in that case, simple "carrying a Type and casting to it" will not help at all. For such things you will probably need dynamic proxies.
Since I already got chatty, last (a bit useless, but you may still want to hear it) note: It actually is possible to force a "cast" to a type stored in a 'Type'. You can do that with expressions. You can dynamically build an Expression<>, bind it with correct Type object, and invoke.
Borrowing code from https://stackoverflow.com/a/3983342/717732 it would look like:
public static ???? castAndReturn(object item, Type type)
{
var p = Expression.Parameter(typeof(object), "i");
var c = Expression.Convert(p, type);
var ex = Expression.Lambda<Func<object, ????>>(c, p).Compile();
return ex(item);
}
but again, what return type you'd put into the ???? placeholders, hm? The only possibilities are object, dynamic, or a custom well-known common-base-type. Back to square one. D'oh. Sorry. No really, way.
It sounds like you are trying to implement a property container exposing a generic indexer, which is (as you know) not possible in C#. However, a similar strategy can be implemented following the patterns seen in the IEditorOptions interface. In particular, note the following characteristics:
The strong type associated with a key is represented by creating the EditorOptionKey<T> generic type instead of using just a string.
The GetOptionValue<T> and SetOptionValue<T> methods replace your current use of an indexer property. The generic type parameter for these methods is inferred from the EditorOptionKey<T> passed as a parameter.
Code using this class might look like the following (using several fields from the DefaultOptions class):
IEditorOptions options = ...;
bool replicate = options.GetOptionValue(DefaultOptions.ReplicateNewLineCharacterOptionId);
options.SetOptionValue(DefaultOptions.IndentSizeOptionId, 2);
options.SetOptionValue(DefaultOptions.ConvertTabsToSpacesOptionId, true);

Is it possible to set custom (de)serializers for open generic types in ServiceStack.Text?

I have a type like this:
class Foo<T>
{
public string Text { get; set; }
public T Nested { get; set; }
public static string ToJson(Foo<T> foo) { [...] }
}
ToJson serializes a Foo<Bar> instance to JSON in a way that is impossible to achieve by tweaking JsConfig. Also, ToJson relies on ServiceStack.Text to serialize Nested, which can be an instance of Foo<Baz>.
Unfortunately, the way JsConfig is implemented implies that there will be a JsConfig<T> set of static variables for Foo<Bar> and other for Foo<Baz>. Also, AFAIK, ServiceStack.Text offers no way to configure JSON serialization for open generic types (i.e.: something like JsConfig.Add(typeof(Foo<>), config)). I tried to solve this issue by creating this static constructor for Foo<T>:
static Foo() {
JsConfig<Foo<T>>.RawSerializeFn = ToJson;
}
This doesn't work all the time. It depends on the order the static constructors are invoked by the runtime. Apparently, ServiceStack.Text caches serializers functions and sometimes is doing it before the static constructor is called depending on the order operations are invoked in the API, so:
var outer = new Foo<Baz> { Text = "text" };
outer.ToJson(); // OK, because Nested is null
var inner = new Foo<Bar>();
inner.ToJson(); // OK, because JsConfig<Foo<Bar>>.RawSerializeFn is Foo<T>.ToJson
outer.Nested = inner;
outer.ToJson(); // NOT OK, because SS.Text uses the default serializer for Foo<T>, not Foo<T>.ToJson
I can't set all the serializers in JsConfig<Foo<T>> beforehand because T can be virtually any type, even other generic types.
Is it possible to define custom serialization routines for open generic types (that can be nested) in ServiceStack.Text?
I solved for this in my own way with a wrapper and a custom deserializer. I created a base type for all of my abstract types. That base type tells the system which type it is:
public class SetSettingItemBase
{
public string Key { get; set; }
public string ValueType { get; set; }
}
So the base is essentially the metadata -- the setting key + the value type. The object DTO, then, simply extends it by adding the actual value:
public class SetSettingItem : SetSettingItemBase
{
public object Value { get; set; }
}
Note that it's just an object. This is the DTO, not my actual object. I can cast it later, or convert it to a real/generic type after serialization.
My custom serialization then is:
JsConfig<SetSettingItem>.RawDeserializeFn = str =>
{
var baseSettings = str.FromJson<SetSettingItemBase>();
var ret = baseSettings.MapTo<SetSettingItem>();
if(true) // actual condition removed here... unimportant to the example
{
var dataType = Constants.KnownSettingsTypes[baseSettings.ValueType];
var method = typeof(JsonExtensions).GetMethod("JsonTo").MakeGenericMethod(dataType);
var key = "Value";
var parsed = JsonObject.Parse(str);
if(parsed.Object(key) == null)
key = "value";
ret.Value = method.Invoke(null, new object[] { parsed, key });
}
return ret;
};
This method first deserializes to the simple base. So the Value passed in from the DTO is ignored when deserializing baseSettings. I then call MapTo to prepare the actual SetSettingItem DTO. MapTo is just a wrapper around AutoMapper. You could just as easily use SS's built in mapper here.
For security, I have a set list of types that I allow as settings. Example:
KnownSettingsTypes.Add("string", typeof(string));
KnownSettingsTypes.Add("int", typeof(int));
KnownSettingsTypes.Add("nullableint", typeof(int?));
KnownSettingsTypes.Add("nullablepercentage", typeof(double?));
KnownSettingsTypes.Add("feegrid", typeof(FeeGrid));
After that, I use reflection to get the JsonTo method, passing in the generic type parameter dynamically from the KnownSettingsTypes dictionary.
And then finishing it all up, I parse the object using the generic JsonObject.Parse method and then looking for the Value or value (depending on case sensitivity) and explicitly convert that JsonObject using the dynamic method I created earlier.
The end result is I can pass in settings of all different types here as a part of my DTOs.
This served my purposes for the time being, but looking at the example I could see it improving in two ways:
After parsing, I could convert my SetSettingItem to a SettingItem<T> so I could use it as a strongly-typed object in my code. Remember, this example is just for the DTOs to get it across the wire.
Instead of requiring the person to pass in the type for me to check against, I could check against the setting Key to know which type it is supposed to be and parse accordingly. In my example, even if I check against the master list of settings and their types, I'd still probably require them to pass in the type just as a precaution and throw an exception if they didn't match.

Access to methods in Object type

I'm trying to figure out how to do something like the following (that was typed off the top of my head so it might not be 100% accurate, but it should get the point across) in csharp, but I'm not really sure how.
class Test
{
private __construct() {}
public static function GetInstance($name)
{
if (file_exists($name . ".php"))
{
return new $name();
}
else
{
return null;
}
}
}
I know how to get the object I want back based on the input, but I have to return an Object, because I'm not sure which one the caller will request. However, when I have no idea how to get access to the methods in the returned Object.
Assuming I understand your pseudo code correctly you will have to cast the resulting object to the type that you are expecting so you can access the public methods of that type:
Foo myFoo = (Foo) Test.GetInstance("Foo");
string bar = myFoo.Bar();
Also check the Activator.CreateInstance() method which basically does what your GetInstance method wants to do.
If I interpret your question correctly I think you want to create an object by type name. There are a number of ways to do this. This is one example:
public static class Test
{
public object CreateInstance(string typeName)
{
Type type = Type.GetType(typeName);
return Activator.CreateInstance(type);
}
}
This assumes the typeName is a full type name including namespace, and that this type has a default (no argument) constructor. Otherwise the method will fail. Use for example like this (you have to cast to User your type in order to access the methods in the User type.
User user = (User)Test.CreateInstance("Some.Namespace.User");
// Now methods and propertes are available in user
Console.WriteLine("User name: "+user.Name);
Hope this thread also helps. Here is some more reflection examples.
// create instance of class DateTime
DateTime dateTime = (DateTime)Activator.CreateInstance(typeof(DateTime));
// create instance of DateTime, use constructor with parameters (year, month, day)
DateTime dateTime = (DateTime)Activator.CreateInstance(typeof(DateTime),
new object[] { 2008, 7, 4 });

Detecting if class property is a reference type

Is it possible when looking at a class' properties to detect if any of them is a reference type.
Take below as an example:
public class Client
{
public int Id { get; set; }
public string Name { get; set; }
}
public class ProgrammeClient
{
public int Id { get; set; }
public bool IsActive { get; set; }
public IClient Client { get; set; }
}
ProgrammeClient: -
Id and IsActive are properties but Client is a reference type. Is there a way of detecting this?
Many thanks,
Kohan.
Addendum
The reason i ask is: I am using a mapper that checks types are the same before matching property names and copying the values. My hope is to detect classes and override the type matching and simply copy the classes properties if the THEY type match.
Well, it sounds like you may be trying to detect the difference between a value type and a reference type. You can find that out using Type.IsValueType... but be aware that value types can easily have properties too. (Think about DateTime for example.) Also, some types which you may want to regard as "not objects" are reference types - string being a prime example.
Another option would be to use Type.IsPrimitive - is that what you're looking for? If so, you should be aware that decimal, DateTime and string are not primitive types.
If you can describe exactly what makes a type an "object" in your way of thinking (or rather, in whatever way makes a semantic difference in what you're trying to do with your type). I suspect you don't currently have a very clear set of criteria - coming up with those criteria may well clarify other aspects of your current task, too.
You can use a little reflection to see if a property is a value type or a class type. Class is probably what you mean by "object". All types in .NET derive from the object type.
Client.GetType().IsClass
Or you can loop through all properties and see which are compound
foreach(var p in ProgrammeClient.GetType().GetProperties())
{
if(p.PropertyType.IsClass) Console.WriteLine("Found a class");
}
Check if the type is a string and check if it is a class.
public static bool IsNonStringClass(this Type type)
{
if (type == null || type == typeof(string))
return false;
return typeof(Type).IsClass;
}
All properties in your example return objects, as everything is an object in .NET; int and bool are objects. If you mean a reference type, as opposed to value types, then you can do the following:
foreach (PropertyInfo pi in typeof(Client).GetProperties()) {
if (pi.PropertyType.IsClass) {
// reference type
// DoMyFunkyStuff
}
}
You can enumerate the properties via Reflection, and check them:
bool ContainsOnlyValues() {
return typeof(ProgrammeClient).GetProperties().All(x => x.PropertyType.IsValueType);
}
The Type.IsvalueType property can reveal this.
Id.GetType().IsValueType
This will be True for Id, false for a class
If using TypeSupport nuget package you can simply do:
typeof(ProgrammeClient).GetExtendedType().IsReferenceType;
TypeSupport does inspection and provides deeper insight on the capabilities of a given type, handling things like strings, enums etc and makes it easier to code these types of things.

Categories

Resources