Comment décompresser d’un object à un autre qu’il contient, sans savoir ce type lors de la compilation?

Au moment de l’exécution, j’obtiens une instance de type quelconque. Comment décompresser le type sous-jacent?

Object obj; Ssortingng variable = "Some text"; obj = variable // boxing; // explicit unboxing, because we know the type of variable at comstack time. var x = (Ssortingng)obj // Now let's pretend that we don't know the type of underlying object at comstack time. Type desiredType = obj.GetType(); // But we can figure out. //And now the question. //How to express something like this: var y = (desiredType)obj; //Need to get unboxed instance of initial variable here; 

Si vous ne connaissez pas le type au moment de la compilation , vous ne pouvez pas décompresser car vous n’avez nulle part où le placer . Tout ce que vous pouvez faire est de le stocker dans un object , qui est: boxed.

Il en va de même pour les types de référence tels que ssortingng : vous ne pouvez pas le convertir au bon type si vous ne connaissez pas le type au moment de la compilation: vous n’avez nulle part où le mettre .

Vous pouvez mettre en casse quelques types, par exemple:

 if(obj is int) { int i = (int)obj; ... } ... 

Une autre astuce qui est parfois (pas souvent) utile est de passer aux génériques . alors au lieu de parler en termes d’ object vous parlez en termes de T Cela a … un usage limité cependant. Le moyen le plus simple de le faire consiste à utiliser dynamicment , par exemple:

 dynamic obj = ... Foo(obj); ... Foo(T val) { ... code with T ... } 

vous pouvez également append des cas spéciaux à cette approche:

 Foo(ssortingng val) { ... code with ssortingng ...} Foo(int val) { ... code with int ...} 

Cependant, franchement, je suggère qu’il soit peut-être préférable de regarder de près ce que vous essayez de faire.

Supposons maintenant que la vraie boxe se produise:

 int v = 5; object o = v; //boxed Type type = o.GetType(); //will return typeof(int) int convertedBack = (int)Convert.ChangeType(o, type); Console.WriteLine (convertedBack); //prints 5 

Remarque, si vous remplacez:

 object convertedBack = Convert.ChangeType(o, type); Console.WriteLine (convertedBack); //it still prints 5 Console.WriteLine (o); //it even print 5 here 

La raison en est que l’object sous-jacent est toujours int . Je viens d’utiliser cet exemple pour vous montrer que la boxe n’a aucune pertinence ici. Vous devez vous fier à une certaine abstraction dans vos opérations et si vous voulez utiliser dynamicment le int vers int , quel type de référence voulez-vous utiliser?

Dans de tels cas, je vais utiliser le modèle de stratégie en utilisant un Dictionary> :

 internal class Program { private static void Main(ssortingng[] args) { var something = new Something(); something.ComputeValue(13); something.ComputeValue(DateTime.Now); something.ComputeValue(DayOfWeek.Monday); Console.ReadKey(); } } internal class Something { private static Dictionary> _Strategies; static Something() { // Prepare all available strategies. _Strategies = new Dictionary>(); _Strategies.Add(typeof(int), ComputeInteger); _Strategies.Add(typeof(DateTime), ComputeDateTime); } public void ComputeValue(object value) { Action action; // Check if we have a matching strategy. if (!_Strategies.TryGetValue(value.GetType(), out action)) { // If not, log error, throw exception, whatever. action = LogUnknownType; } // Perform the matching strategy on the given value. action(value); } private static void ComputeDateTime(object source) { // We get an object, but we are sure that it will always be an DateTime. var value = (DateTime)source; Console.WriteLine("We've got an date time: " + value); } private static void ComputeInteger(object source) { // We get an object, but we are sure that it will always be an int. var value = (int)source; Console.WriteLine("We've got an integer: " + value); } private static void LogUnknownType(object source) { // What should we do with the drunken sailor? var unknownType = source.GetType(); Console.WriteLine("Don't know how to handle " + unknownType.FullName); } } 

Voici un exemple de exactement pourquoi vous feriez cela:

 class MyClass { public int Id {get;set;} public ssortingng Name {get;set;} public decimal Val {get;set;} } int i = 0; var myClassImp = new MyClass(); foreach (var val in new [object]{"10", "My name", "100.21"} // Could be read from some data source, such as an excel spreadsheet { var prop = typeof(MyClass).GetProperties().ElementAt(i++); // !!!!!! THROWS EXCEPTION !!!!!!! prop.SetValue(myClassImp, System.Convert.ChangeType(val, prop.PropertyType), null); } 

La raison en est que la valeur est un object encadré … au moment de l’exécution, vous ne connaissez pas le type, vous devez donc décompresser le prop.PropertyType

Une solution pragmatique; essayez d’utiliser un TypeConverter directement, et si cela échoue, convertissez-le en chaîne et inversement: –

 private static T GetValueOfType(this ManagementBaseObject MBO, Ssortingng FieldName) { T lResult; try { Object lObj = MBO[FieldName]; var lSrcType = lObj.GetType(); var lDestType = typeof(T); if (lDestType.IsValueType && lDestType.IsAssignableFrom(lSrcType)) { lResult = (T)lObj; return lResult; } var lDestTC = TypeDescriptor.GetConverter(typeof(T)); if (lDestTC.CanConvertFrom(lSrcType)) { lResult = (T)lDestTC.ConvertFrom(lObj); } else { var lSrcTC = TypeDescriptor.GetConverter(lSrcType); Ssortingng lTmp = lSrcTC.ConvertToInvariantSsortingng(lObj); lResult = (T)lDestTC.ConvertFromInvariantSsortingng(lTmp); } } catch { lResult = default(T); } return lResult; } 
 public static ssortingng GetType(object data) { Type type = data.GetType(); return Convert.ChangeType(data, type).GetType().Name; } 

Bonjour, cette méthode reçoit les données d’object et retourne le nom du type de chaîne de l’object. J’espère que c’est ce dont vous avez besoin.

Utiliser des expressions:

var y = DynamicCast (obj, désiréType);

 static object DynamicCast(object source, Type type) { var parameter = Expression.Parameter(typeof(object), "input"); var cast = Expression.TypeAs(Expression.Convert(parameter, type), typeof(object)); var lambda = Expression.Lambda>(cast, parameter); var func = lambda.Comstack(); return func(source); } 

vous pouvez essayer d’utiliser le runtime dynamic

  [Test] public void Test_UnboxingAtRuntime() { object boxed = "Hello"; //this line is commented out as it does not comstack // OverloadedMethod(boxed); var result = CallCorrectMethod(boxed); Assert.That(result, Is.EqualTo("ssortingng")); boxed = 1; result = CallCorrectMethod(boxed); Assert.That(result, Is.EqualTo("int")); } public ssortingng CallCorrectMethod(dynamic t) { return OverloadedMethod(t); } public ssortingng OverloadedMethod(ssortingng s) { return "ssortingng"; } public ssortingng OverloadedMethod(int s) { return "int"; }