I have the class:
class Person
{
public string Name { get { return "Antonio"; } }
}
and the Code:
IEnumerable<object> uncknownObject;
uncknownObject = new ObservableCollection<Person>( );
var observCol = uncknownObject.GetType( );
var x = ( ( dynamic )observCol ).GenericTypeArguments[ 0 ];
var y = observCol.GetProperty( "GenericTypeArguments" );
var instance = ( Person )Activator.CreateInstance( x );
Console.WriteLine( instance.Name ); // Print Antonio!!!
why does y == null ?
Note the picture:
the debugger shows that the property GenericTypeArguments should exist and the code shows the opossite. It can be proven that the debugger is right and that property exist because then how come x is not null. If that property exists then why y is equal to null!!!???
Edit
Thanks to Ani I now have:
IEnumerable<object> uncknownObject;
uncknownObject = new ObservableCollection<Person>();
var observCol = uncknownObject.GetType();
var genTypeArgsProperty = typeof(Type).GetProperty("UnderlyingSystemType");
var genTypeArgsValue = (genTypeArgsProperty.GetValue(observCol, null));
var f = genTypeArgsValue.GetType().GetMethod("GetGenericArguments");
IEnumerable<object> result = (IEnumerable<object>)f.Invoke(genTypeArgsValue, null);
var x = result.FirstOrDefault();
var instance = Activator.CreateInstance( (Type)x );
In case of curios why I needed that functionality click here
I don't really understand what you're trying to accomplish with all this meta-meta-reflection, but you seem to have misunderstood what Type.GetProperty does. It gets meta-data for a property on the actual type represented by the System.Type instance (in this case, ObservableCollection<Person>). It does not get meta-data for a property declared on System.Type itself, unless of course you call it on a System.Type representing System.Type itself.
In your case, y is null since ObservableCollection<Person> does not have a property named "GenericTypeArguments".
Try this instead:
var genTypeArgsProperty = typeof(Type).GetProperty("GenericTypeArguments");
var genTypeArgsValue = (Type[]) (genTypeArgsProperty.GetValue(observCol, null));
var onlyTypeArgValue = genTypeArgsValue.Single();
This code works with net framework 4:
IEnumerable<object> uncknownObject;
uncknownObject = new ObservableCollection<Person>();
var observCol = uncknownObject.GetType();
var x = ((dynamic) observCol).UnderlyingSystemType.GetGenericArguments()[0];
var y = observCol.GetGenericArguments();
var instance = (Person)Activator.CreateInstance(x);
Console.WriteLine(instance.Name); // Print Antonio!!!
Related
So i have the following List:
List<AttackStyle> AttackStyles = new List<AttackStyle>();
With the following types of objects:
AttackStyle lStyle = new AttackStyle();
lStyle.Name = "Attack Achilles";
lStyle.ParameterID = 0;
lStyle.Forward = Vector3.forward;
lStyle.HorizontalFOA = 70f;
lStyle.VerticalFOA = 40f;
lStyle.DamageModifier = 1f;
lStyle.ActionStyleAlias = "Jump";
lStyle.IsInterruptible = true;
AttackStyles.Add(lStyle);
Now i wish to find the field ParameterID where the ActionStyleAlias is equal to a value (for instance "Jump")
This is for a Unity application so the search / find needs to be as fast as possible.
var result = AttackStyles.FirstOrDefault(x => x.ActionStyleAlias == "Jump").ParameterID;
The straight solution is:
var pId = AttackStyles.FirstOrDefault(x=> x.ActionStyleAlias == "Jump")?.ParameterID
But if you want to get a better performance, it would be better, to index the most useful property which you want. Therefore, construct a dictionary on the most useful fields to get a better performance in time. For example:
var styles = new Dictionary<string, AttackStyle>();
styles.Add("Jump", new AttackStyle()
{
Name = "Attack Achilles",
ParameterID = 0,
Forward = Vector3.forward,
HorizontalFOA = 70f,
VerticalFOA = 40f,
DamageModifier = 1f,
ActionStyleAlias = "Jump",
IsInterruptible = true
});
Then, find the object by this:
var pId = styles["Jump"].ParamterId;
or if it might be null:
if(styles.Keys.Contains("Jump"))
var pId = styles["Jump"].ParamterId;
var param = AttackStyles.First(x => x.ActionStyleAlias.Equals(value)).ParameterID;
Let's return first ParameterID if there's the required item in the collection; -1 otherwise:
var result = AttackStyles
.Where(item => item.ActionStyleAlias == "Jump")
.Select(item => item.ParameterID)
.DefaultIfEmpty(-1)
.First();
You can try extension methods. Also you should consider null cases:
static class Extensions
{
public static int? FindParameterId(this List<AttackStyle> values, string actionStyleAlias)
{
return values.FirstOrDefault(x => x.ActionStyleAlias == actionStyleAlias)?.ParameterID;
}
}
Then use it:
List<AttackStyle> attackStyles = new List<AttackStyle>();
var parameterId = attackStyles.FindParameterId("Jump");
Can I detect (using roslyn) that x reference in the lambda body is closure over outer variable x, not some variable local to lambda itself?
var x = "foo";
var a = string[0];
a.Any(i => i == x);
Yup. You can use the DataFlowAnalysis API.
var tree = CSharpSyntaxTree.ParseText(
#"
class C{
void M(){
var x = ""foo"";
var a = new string[0];
var testing = a.Any(i => i == x);
}
}
");
var Mscorlib = PortableExecutableReference.CreateFromAssembly(typeof(object).Assembly);
var compilation = CSharpCompilation.Create("MyCompilation",
syntaxTrees: new[] { tree }, references: new[] { Mscorlib });
var model = compilation.GetSemanticModel(tree);
var lambda = tree.GetRoot().DescendantNodes().OfType<LocalDeclarationStatementSyntax>().Last();
var dataFlowAnalysis = model.AnalyzeDataFlow(lambda);
var capturedVariables = dataFlowAnalysis.Captured;
foreach(var variable in capturedVariables)
{
//Do something
}
https://github.com/mjsabby/RoslynClrHeapAllocationAnalyzer/blob/master/ClrHeapAllocationsAnalyzer/DisplayClassAllocationAnalyzer.cs#L58
(1) Get Semantic Model
(2) Check for AnonymousMethodExpressionSyntax / SimpleLambdaExpressionSyntax / ParenthesizedLambdaExpressionSyntax
(3) Pass that node to AnalyzeDataFlow extension method on the SemanticModel
(4) Iterate over the .Captured property
Type t = Type.GetType(obj.ToString());
PropertyInfo p = t.GetProperty("Test");
dynamic kk = p.GetValue(obj, null);
In this, Test is an int List. I need to get the sum of all the values from int list ie., kk.
var list = p.GetValue(obj, null) as IEnumerable<int>;
var result = list.Sum();
// Type t = Type.GetType(obj.ToString());
Type t = obj.GetType(); // You might be able to replace the above line with this, simpler verison.
PropertyInfo p = t.GetProperty("Test");
object kk = p.GetValue(obj, null);
int Sum = (kk as List<int>).Sum();
I know that this can be rewritten using a lambda expression. But I cant seem to figure it out. does anyone have an opinion on how it should be written using a lambda.
foreach (var _systemItem in _systemData)
{
foreach (var _institutionItem in _institutionData)
{
if (_systemItem.LookupValue == _institutionItem.OriginalSystemLookupValue)
{
_values.Add(new LookupValue()
{
DisplayText = _institutionItem.LookupText,
Value = _institutionItem.LookupValue
});
}
else
{
_values.Add(new LookupValue()
{
DisplayText = _systemItem.LookupText,
Value = _systemItem.LookupValue
});
}
}
}
Like this:
values.AddRange(from s in _systemData
from i in institutionData
select s.LookupValue == i.OriginalSystemLookupValue ?
new LookupValue {
DisplayText = _institutionItem.LookupText,
Value = _institutionItem.LookupValue
}
: new LookupValue {
DisplayText = _systemItem.LookupText,
Value = _systemItem.LookupValue
}
);
Is _values a List<LookupValue> which is empty to start with? If so, that look might look like this:
_values = (from x in _systemData
from y in _institutionData
let item = x.LookupValue == y.OriginalSystemLookupValue ? x : y
select new LookupValue { DisplayText = item.LookupText,
Value = item.LookupValue })
.ToList();
That assumes that _systemItem and _institutionItem are the same type. If they're unrelated types, you might want to give them a common interface that defines LookupText and LookupValue (or even a ToLookupValue method) and then cast one of the operands in the conditional operator to the interface. For example:
_values = (from x in _systemData
from y in _institutionData
let item = x.LookupValue == y.OriginalSystemLookupValue
? (ILookupSource) x : y
select item.ToLookupValue())
.ToList();
Sure, I have an opinion. I'd write it like this:
var pairs = _systemData.SelectMany(s =>
_institutionData.Select(i => new { System = s, Institution = i }));
_values.AddRange(pairs.Select(x =>
{
bool match = x.System.LookupValue == x.Insitution.OriginalSystemLookupValue;
return match ? new LookupValue(x.Institution) : new LookupValue(x.System);
}));
And move the object initializers for LookupValue into real constructors that take an Institution or System.
var quantSubset =
from userAns in userAnalysis.AllUserAnswers
join ques in userAnalysis.AllSeenQuestions on userAns.QID equals ques.QID
where (ques.QuestionType == "QT")
select new {
QuestionLevel = ques.LevelID,
TimeTaken = userAns.TimeTaken,
Points = userAns.Points,
UsedWeapon = (userAns.UsedBy2 && userAns.UsedHint),
WasCorrect = userAns.WasCorrect.HasValue ? userAns.WasCorrect.Value : null
};
In my select expression I want to select a nullable type WasCorrect (last part of the expression) but apparently I cannot do it the way I am currently trying.
How can I get WasCorrect as nullable type
I tried ?WasCorrect but that also doesnt gives error in Visual Studio.
You need to cast the null value to the nullable type explicitly:
WasCorrect = userAns.WasCorrect.HasValue ?
userAns.WasCorrect.Value : (TheTypeName?)null
Otherwise C# won’t know which type the conditional expression should be.
Apart from that, the code is completely redundant. You can simply write:
WasCorrect = userAns.WasCorrect
You absolutely must be able to write
select new { WasCorrect = userAns.WasCorrect }
if userAns.WasCorrect is Nullable<bool>.
This code executes without a problem:
class Test {
public bool? NullableBool { get; set;}
}
class MainClass
{
public static void Main ()
{
Test t1 = new Test { NullableBool = true };
var a1 = new { NB = t1.NullableBool };
Test t2 = new Test { NullableBool = null };
var a2 = new { NB = t2.NullableBool };
}
}