Passing Nullable Int using reflection - c#

i am using this code
//Rextester.Program.Main is the entry point for your code. Don't change it.
//Compiler version 4.0.30319.17929 for Microsoft (R) .NET Framework 4.5
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Reflection;
namespace Rextester
{
public class Program
{
public static void Main(string[] args)
{
new Program().DoTest();
}
public void DoTest()
{
var a = LoggingAdvice<asd>.Create(new a());
a.targetMethod("nadeem", 123, null);
}
}
public class LoggingAdvice<T> : DispatchProxy
{
private T _decorated;
protected override object Invoke(MethodInfo targetMethod, object[] args)
{
var result = targetMethod.Invoke(_decorated, args);
var resultTask = result as Task;
return result;
}
public static T Create(T decorated)
{
object proxy = Create<T, LoggingAdvice<T>>();
((LoggingAdvice<T>)proxy).SetParameters(decorated);
return (T)proxy;
}
private void SetParameters(T decorated)
{
if (decorated == null)
{
throw new ArgumentNullException(nameof(decorated));
}
_decorated = decorated;
}
}
public class asd
{
public asd()
{
}
public int targetMethod(string name, int number, int? count)
{
Console.WriteLine(name);
Console.WriteLine(number);
Console.WriteLine(count.HasValue ? count.Value.ToString() : "NULL");
return 1;
}
}
}
the most important thing about it, is this line of code
var result = targetMethod.Invoke(_decorated, args);
the target method has 3 parameters, one of them is nullable integer as the following
public int targetMethod(string name, int number, int? count)
the args that is getting passed to Invoke method has the following values as you can view it in the visual studio debugging mode:
["nadeem", 123, (null)]
the invoke is raising an exception that i cannot convert string to nullable integer.
how i can avoid this type of issue, note that i am not sure which function i am going to be invoked, i would only know it on runtime.

Related

Cannot convert from 'Program.state<TState>' to 'Program.state<object>' passing custom type to class in a dictionnary

I'm working on a lightweight state system for my app.
I'm kinda confused:
how can I pass type to my class in a dictionary?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
public class Program
{
public class state<TState>
{
private TState? _value;
public TState Value { get { return _value; } set { if (!_value.Equals(value)) _value = value;if(onChange != null ) onChange(Value); } }
private Action<TState>? onChange;
public state(TState val, Action<TState>? action)
{
_value = val;
onChange = action;
}
}
public class stateHolder
{
public Dictionary<string, object> states = new();
public void AddState<TState>(string name, TState value, Action<TState>? onChange)
{
state<TState> state = new state<TState>(value, onChange);
states[name] = state;//ERROR HERE
}
public object? this[string stateName] { get{ return states[stateName];} }
}
public static void Main()
{
stateHolder states = new();
states.AddState<string>("test","Yeah",(x)=>Console.WriteLine(x));
state<string> test = states["test"] as state<string>;
test.Value = "Hey";//should console log Hey
Console.WriteLine("Hello World");
test.Value = "Hello";//should console log Hey
}
}
I'm not a beginner, but not a pro at all. I code when I have freetimes so sorry if my code is dumb if you can help me would be nice thanks in advance links bottom
Fiddle link https://dotnetfiddle.net/GxdLGb
Collab link https://dotnetfiddle.net/GxdLGb#&togetherjs=G2ED70iyE8

Can't dynamically invoke a method in c#

I have a class whose method I want to invoke dynamically. But I am not able to do it. Am I missing something?
public class P_WATER
{
private int[] jDS = new int[20];
private int n;
public int[] JDS { get => jDS; set => jDS = value; }
public int N { get => n; set => n = value; }
public void P_WATER1()
{
//something...
}
}
public class Test
{
P_WATER P_WATERState1 = new P_WATER();
PLibStateList.Add(P_WATERState1);
// Try to invoke methods from each objects.
foreach (object item in StateUtility.PLibStateList)
{
Type objType= item.GetType();
objType.InvokeMember(objType.Name + "1", BindingFlags.InvokeMethod, null, item, null);
}
}
When trying to invoke the method I am getting the following exception:
Could not load file or assembly 'System.Runtime, Version=4.2.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies. The system cannot find the file specified.
But my assembly is well bound to the project.
I've tried the same code (with little modifications) in VS2019 (Console App) and worked just fine... weird... check the using statements for ambiguity (just in case):
using System;
using System.Collections.Generic;
using System.Reflection;
My full code:
using System;
using System.Collections.Generic;
using System.Reflection;
namespace cant_dynamically_invoke_a_method_in_c_sharp
{
class Program
{
static void Main(string[] args)
{
Test.InvokeStuff();
}
}
public class P_WATER
{
private int[] jDS = new int[20];
private int n;
public int[] JDS { get => jDS; set => jDS = value; }
public int N { get => n; set => n = value; }
public void P_WATER1()
{
//something...
Console.WriteLine("Success!");
}
}
public class Test
{
public static void InvokeStuff()
{
// Needed to mock this up
List<P_WATER> PLibStateList = new List<P_WATER>();
P_WATER P_WATERState1 = new P_WATER();
PLibStateList.Add(P_WATERState1);
// Try to invoke methods from each objects.
foreach (object item in PLibStateList)
{
Type objType = item.GetType();
objType.InvokeMember(objType.Name + "1", BindingFlags.InvokeMethod, null, item, null);
}
}
}
}
Entered the method successfuly:
Regards!

Access result of Task<T> without knowing T - postsharp

I am trying to use postsharp modify the return values of async methods. Is it possible to get the result of a Task at runtime without knowing T?
i.e.
public void OnSuccess(MethodExecutionArgs args)
{
var returnValue = args.ReturnValue;
// returnType is Task<T>
var returnType = returnValue.GetType();
// Is it possible to access the result of the task?
// If T was known then I could cast:
// ((Task<T>) returnValue).ContinueWith(t => t.Result ...)
}
Without reflection, you'd need to use and interface. Also with PostSharp 5.0, you get the result itself there in the OnSuccess method instead of the Task<>.
This example works with PostSharp 5.0:
using System;
using System.Threading.Tasks;
using PostSharp.Aspects;
using PostSharp.Serialization;
namespace OnMethodBoundaryAsyncTest
{
interface IDirtiness
{
bool Dirty { get; set; }
}
class MyClassWithSomeDirtyObjects : IDirtiness
{
public bool Dirty { get; set; }
}
[PSerializable]
class ReportDirtinessAttribute : OnMethodBoundaryAspect
{
public override void OnSuccess( MethodExecutionArgs args )
{
IDirtiness maybeDirtyObject = args.ReturnValue as IDirtiness;
if ( maybeDirtyObject != null )
{
string dirty = maybeDirtyObject.Dirty ? "is" : "is not";
Console.WriteLine($"{maybeDirtyObject} {dirty} dirty.");
}
}
}
class Program
{
static void Main(string[] args)
{
CreateObject( false ).GetAwaiter().GetResult();
CreateObject( true ).GetAwaiter().GetResult();
}
[ReportDirtiness(ApplyToStateMachine = true)]
static async Task<MyClassWithSomeDirtyObjects> CreateObject( bool dirty )
{
return new MyClassWithSomeDirtyObjects {Dirty = dirty};
}
}
}

C# binary search tree

I was making a test case for some code on binary search tree my professor gave
public static void Main(string [] args)
{
//on my prof's code, public class BinSearchTree<T>
BinSearchTree<int> myTree = new BinSearchTree<int>();
myTree.Insert(10);
myTree.Insert(15);
myTree.Insert(5);
myTree.Insert(2);
myTree.Insert(1);
Console.WriteLine(myTree.ToString());
Console.ReadKey();
}
It compiles, but it displays
BinSearchTree`1[System.Int32]
Can somebody tell me why it displays that?
my prof's code:
public class BinSearchTree<T> where T : IComparable<T>
{
private class OurTreeNode<T>
{
public T Data { get; set; }
public OurTreeNode<T> Left;
public OurTreeNode<T> Right;
public OurTreeNode(T d = default(T), OurTreeNode<T> leftnode = null, OurTreeNode<T> rightnode = null)
{
Data = d;
Left = leftnode;
Right = rightnode;
}
public override string ToString()
{
return Data.ToString();
}
}
//...other methods
//prof's Insert method
public void Insert(T newItem)
{
mRoot = Insert(newItem, mRoot);
}
private OurTreeNode<T> Insert(T newItem, OurTreeNode<T> pTmp)
{
if (pTmp == null)
return new OurTreeNode<T>(newItem, null, null);
else if (newItem.CompareTo(pTmp.Data) < 0)
pTmp.Left = Insert(newItem, pTmp.Left);
else if (newItem.CompareTo(pTmp.Data) > 0)
pTmp.Right = Insert(newItem, pTmp.Right);
else
throw new ApplicationException("...");
return pTmp;
}
}
I tried adding a ToString() method after the Insert method but it gives me an error when I used foreach. Is there a way of displaying it without making too much extra methods?
The class is using the default (Object's) ToString() implementation. You have 2 options:
walk though the elements of the tree and print it yourself
ask the author to implement/override the ToString() method
Can somebody tell me why it displays that?
It displays that because ToString() prints the type definition.
Default implementations of the Object.ToString method return the fully qualified name of the object's type. (from the docs)
For instance, the following short program prints System.Collections.Generic.List`1[System.Int32], which is the type of List<int>.
using System;
using System.Collections.Generic;
public class Program
{
public static void Main(string[] args)
{
List<int> myTree = new List<int>();
myTree.Add(10);
Console.WriteLine(myTree.ToString());
}
}
Here are the rudiments of how to override the ToString() method to produce some meaningful output.
using System;
using System.Collections.Generic;
public class Program
{
public static void Main(string[] args)
{
BinSearchTree<int> myTree = new BinSearchTree<int>();
myTree.Insert(10);
myTree.Insert(15);
Console.WriteLine(myTree.ToString());
}
}
public class BinSearchTree<T> where T : IComparable<T>
{
private List<T> values = new List<T>();
// rest of class omitted for clarity
public void Insert(T val) {
values.Add(val);
}
public override string ToString() {
var result = string.Empty;
foreach(var v in values)
{
result += v + ", ";
}
return result;
}
}
Output
10, 15,
As you have created the object of BinaryTree Class and have not overridden the ToString() method inside BinaryTree Class. You have not created object of OurTreeNode class and not calling ToString() method overriden inside it. Hence it is giving you the default ToString() method output of BinaryTree Class.
BinSearchTree<int> myTree = new BinSearchTree<int>();
You are calling
Console.WriteLine(myTree.ToString());

How to remove SyntaxToken when using a Code Fix Provider

I'm working on a code base which has the purpose to format code. In some instances, I have to remove syntax tokens such as the keyword "params" inside the parameter list if I found one and it's redundant or remove some unneeded braces ( "{" "}").
The thing is, it's so hard and uneasy to remove syntax token from the syntax tree. I have tried many different solutions that you can find below, but for the life of me, I cannot succeed. I'd like a solution that could work for any syntax token U might encounter and that I need to possibly remove from the syntax tree.
In the following case, I have built an analyzer that is currently functionnal but the code fix provider is not quite working... (It's a case of redundant params keyword usage).
//UPDATE - I have provided full code of Analyzer/Code fix provider / NUnit tests
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using System.Collections.Immutable;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Formatting;
namespace RefactoringEssentials.CSharp.Diagnostics
{
[ExportCodeFixProvider(LanguageNames.CSharp), System.Composition.Shared]
public class RedundantParamsCodeFixProvider : CodeFixProvider
{
public override ImmutableArray<string> FixableDiagnosticIds
{
get
{
return ImmutableArray.Create(CSharpDiagnosticIDs.RedundantParamsAnalyzerID);
}
}
public override FixAllProvider GetFixAllProvider()
{
return WellKnownFixAllProviders.BatchFixer;
}
public async override Task RegisterCodeFixesAsync(CodeFixContext context)
{
var document = context.Document;
var cancellationToken = context.CancellationToken;
var span = context.Span;
var diagnostics = context.Diagnostics;
var root = await document.GetSyntaxRootAsync(cancellationToken);
var diagnostic = diagnostics.First();
var node = root.FindNode(context.Span) as ParameterSyntax;
if (node == null)
return;
if (!node.Modifiers.Any(x => x.IsKind(SyntaxKind.ParamsKeyword)))
return;
var oldParameterNode = node;
var paramList = node.Parent as ParameterListSyntax;
if (paramList == null)
return;
//var newRoot = root.ReplaceNode(
// oldParameterNode.Parent as ParameterListSyntax,
// paramList.WithParameters
// (SyntaxFactory.SeparatedList(paramList.Parameters.ToArray()))
// .WithLeadingTrivia(node.GetLeadingTrivia())
// .WithTrailingTrivia(node.GetTrailingTrivia()))
// .WithAdditionalAnnotations(Formatter.Annotation);
//var paramsKeyword = (node.Modifiers.FirstOrDefault(x => x.IsKind(SyntaxKind.ParamsKeyword)));
//var indexParams = node.Modifiers.IndexOf(paramsKeyword);
//var syntaxListWithoutParams = node.Modifiers.RemoveAt(indexParams);
//node.ReplaceToken(paramsKeyword, syntaxListWithoutParams.AsEnumerable());
context.RegisterCodeFix(CodeActionFactory.Create(node.Span, diagnostic.Severity, "Remove 'params' modifier", token =>
{
var newNode = SyntaxFactory.Parameter(node.AttributeLists,node.Modifiers.Remove(SyntaxFactory.Token(SyntaxKind.ParamsKeyword)),node.Type,node.Identifier,node.Default);
var newRoot = root.ReplaceNode(node, newNode);
return Task.FromResult(document.WithSyntaxRoot(newRoot));
}), diagnostic);
//context.RegisterCodeFix(CodeActionFactory.Create(node.SKCpan, diagnostic.Severity, , document.WithSyntaxRoot(newRoot)), diagnostic);
}
}
}
This is the use cases in my situation.
using System;
using NUnit.Framework;
using RefactoringEssentials.CSharp.Diagnostics;
namespace RefactoringEssentials.Tests.CSharp.Diagnostics
{
[TestFixture]
public class RedundantParamsTests : CSharpDiagnosticTestBase
{
[Test]
public void TestBasicCase()
{
Analyze<RedundantParamsAnalyzer>(#"class FooBar
{
public virtual void Foo(string fmt, object[] args)
{
}
}
class FooBar2 : FooBar
{
public override void Foo(string fmt, $params object[] args$)
{
System.Console.WriteLine(fmt, args);
}
}", #"class FooBar
{
public virtual void Foo(string fmt, object[] args)
{
}
}
class FooBar2 : FooBar
{
public override void Foo(string fmt, object[] args)
{
System.Console.WriteLine(fmt, args);
}
}");
}
[Test]
public void TestValidCase()
{
Analyze<RedundantParamsAnalyzer>(#"class FooBar
{
public virtual void Foo(string fmt, object[] args)
{
}
}
class FooBar2 : FooBar
{
public override void Foo(string fmt, object[] args)
{
System.Console.WriteLine(fmt, args);
}
}");
}
[Test]
public void ValideParamsUsageTests()
{
Analyze<RedundantParamsAnalyzer>(#"class FooBar
{
public virtual void Foo(string fmt, params object[] args)
{
}
}
class FooBar2 : FooBar
{
public override void Foo(string fmt, params object[] args)
{
System.Console.WriteLine(fmt, args);
}
}");
}
[Test]
public void TestDisable()
{
Analyze<RedundantParamsAnalyzer>(#"class FooBar
{
public virtual void Foo(string fmt, object[] args)
{
}
}
class FooBar2 : FooBar
{
// ReSharper disable once RedundantParams
public override void Foo(string fmt, params object[] args)
{
System.Console.WriteLine(fmt, args);
}
}");
}
}
}
For those who might be interested in how I determine that the params is redundant, here's the logic:
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
using System.Collections.Immutable;
using System.Linq;
namespace RefactoringEssentials.CSharp.Diagnostics
{
[DiagnosticAnalyzer(LanguageNames.CSharp)]
public class RedundantParamsAnalyzer : DiagnosticAnalyzer
{
private static readonly DiagnosticDescriptor descriptor = new DiagnosticDescriptor(
CSharpDiagnosticIDs.RedundantParamsAnalyzerID,
GettextCatalog.GetString("'params' is ignored on overrides"),
GettextCatalog.GetString("'params' is always ignored in overrides"),
DiagnosticAnalyzerCategories.RedundanciesInDeclarations,
DiagnosticSeverity.Warning,
isEnabledByDefault: true,
helpLinkUri: HelpLink.CreateFor(CSharpDiagnosticIDs.RedundantParamsAnalyzerID),
customTags: DiagnosticCustomTags.Unnecessary
);
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(descriptor);
public override void Initialize(AnalysisContext context)
{
context.RegisterSyntaxNodeAction(
(nodeContext) =>
{
Diagnostic diagnostic;
if (TryGetParamsDiagnostic(nodeContext, out diagnostic))
{
nodeContext.ReportDiagnostic(diagnostic);
}
},
SyntaxKind.ParameterList
);
}
//I think it's a better decision to head in this direction instead of MethodDeclaration.
private static bool TryGetParamsDiagnostic(SyntaxNodeAnalysisContext nodeContext, out Diagnostic diagnostic)
{
diagnostic = default(Diagnostic);
if (nodeContext.IsFromGeneratedCode())
return false;
var paramList = nodeContext.Node as ParameterListSyntax;
var declaration = paramList?.Parent as MethodDeclarationSyntax;
if (declaration == null)
return false;
if (declaration.Modifiers.Count == 0 || !declaration.Modifiers.Any(SyntaxKind.OverrideKeyword))
return false;
var lastParam = declaration.ParameterList.Parameters.LastOrDefault();
SyntaxToken? paramsModifierToken = null;
if (lastParam == null)
return false;
foreach (var x in lastParam.Modifiers)
{
if (x.IsKind(SyntaxKind.ParamsKeyword))
{
paramsModifierToken = x;
break;
}
}
if (!paramsModifierToken.HasValue ||
!paramsModifierToken.Value.IsKind(SyntaxKind.ParamsKeyword))
return false;
diagnostic = Diagnostic.Create(descriptor, lastParam.GetLocation());
return true;
}
}
In this case, you don't want to remove the whole node, rather you just want to remove the params modifier. Since SyntaxNodes are immutable, you need to create a new node with the appropriate modifiers using the WithModifiers method:
public async override Task RegisterCodeFixesAsync(CodeFixContext context)
{
var diagnostic = context.Diagnostics.First();
context.RegisterCodeFix(CodeAction.Create("Remove 'params' modifier", async token =>
{
var document = context.Document;
var root = await document.GetSyntaxRootAsync(token);
var fullParameterNode = root.FindNode(diagnostic.Location.SourceSpan, false) as ParameterSyntax;
// Keep all modifiers except the params
var newModifiers = fullParameterNode.Modifiers.Where(m => !m.IsKind(SyntaxKind.ParamsKeyword));
var syntaxModifiers = SyntaxTokenList.Create(new SyntaxToken());
syntaxModifiers.AddRange(newModifiers);
var updatedParameterNode = fullParameterNode.WithModifiers(syntaxModifiers);
var newDoc = document.WithSyntaxRoot(root.ReplaceNode(fullParameterNode, updatedParameterNode));
return newDoc;
}, "KEY"), diagnostic);
}
As for a generic remove option for syntax, I don't know of one that is easy to use. The Node.ReplaceSyntax is a rather complicated method and I usually find it easier to work with the ReplaceNode or RemoveNode methods.

Categories

Resources