dotnetanalyzers / reflectionanalyzers Goto Github PK
View Code? Open in Web Editor NEWAnalyzers checking System.Reflection
License: MIT License
Analyzers checking System.Reflection
License: MIT License
Given:
class Foo : Base
{
}
public class Base
{
public static class PublicStatic
{
}
public class Public
{
}
private static class PrivateStatic
{
}
private class Private
{
}
}
Does GetNestedType
always return null?
var type = typeof(Foo).GetNestedType(nameof(Public), BindingFlags.Public | BindingFlags.FlattenHierarchy)
Throws at runtime.
GetCustomAttribute<FooAttribute>()
instead of (FooAttribute)GetCustomAttribute(typeof(FooAttribute))
โI keep seeing this.
Including static vs instance.
var bar = (int)typeof(Foo).GetMethod("Bar").Invoke();
Before:
namespace RoslynSandbox
{
using System;
using System.Reflection;
using System.Windows.Controls;
class C
{
private static readonly Type TemplatedAdornerType = typeof(AdornedElementPlaceholder).Assembly.GetType("MS.Internal.Controls.TemplatedAdorner", throwOnError: true);
private static readonly MethodInfo ClearChildMethod = TemplatedAdornerType.GetMethod("ClearChild");
}
}
After:
namespace RoslynSandbox
{
using System;
using System.Reflection;
using System.Windows.Controls;
class C
{
private static readonly Type TemplatedAdornerType = typeof(AdornedElementPlaceholder).Assembly.GetType("MS.Internal.Controls.TemplatedAdorner", throwOnError: true);
private static readonly Action<Adorner> ClearChildMethod = (Action<Adorner>)Delegate.CreateDelegate(typeof(Action<Adorner>), TemplatedAdornerType.GetMethod("ClearChild"), throwOnBindFailure: true);
}
}
I have encountered a situation in the past where public vs private depended on the version of the framework the code was running against. (using reflection to access a private member that was later made public)
Maybe warn for types in sln?
Forms of object != null && type.IsAssignableFrom(obj.GetType())
should be replaced with type.IsInstanceOfType(obj)
.
Not sure about this one, but I picked up on this at https://github.com/dotnet/corefx/issues/23762#issuecomment-327223953
and also on a similar issue a long time ago.
GetGenericArguments()
returns parameters (not arguments) if the type is a generic definition, and it returns arguments if the type is a constructed generic.
GenericTypeArguments
is better if you expect the type to be constructed.
GenericTypeParameters
is better if you expect the type to be a definition. It only exists after adding .GetTypeInfo()
though.
If you don't have an expectation about constructed vs definition, I'm not sure how you can meaningfully use GetGenericArguments()
.
Roll our own BindingFlags
Applies to methods (incl constructors) and properties.
Today we only check typeof(Foo).GetMethod("Bar")
for simplicity.
var method = obj.GetType().GetMethod("Bar");
var type = typeof(Foo);
var method = .GetMethod("Bar");
Are two other common cases, we walk a bit and try to find out the type.
Also check that Activator.CreateInstance<T>()
has a public default constructor?
methodInfo.Invoke(null, Array.Empty<object>())
should really be methodInfo.Invoke(null, null)
, constructorInfo.Invoke(new object[0])
should be constructorInfo.Invoke(null)
, etc.
Only if no BindingFlags value is already specified.
| BindingBlags.Public
should be added to preserve the previous visibility behavior.
GetMethod("Foo", BindingFlags.Public | BindingFlags.Public | BindingFlags.Instance)
Or vice versa?
class Foo
{
private static readonly int Value;
}
class Bar : Foo
{
}
Before:
typeof(Bar).GetField("Value", BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.FlattenHierarchy)
After:
typeof(Foo).GetField("Value", BindingFlags.NonPublic | BindingFlags.Static)
Before:
namespace RoslynSandbox
{
using System.Reflection;
class Foo
{
public Foo()
{
var methodInfo = typeof(Foo).GetMethod(nameof(this.Bar);
}
public static void Bar()
{
}
}
}
After:
namespace RoslynSandbox
{
using System.Reflection;
class Foo
{
public Foo()
{
var methodInfo = typeof(Foo).GetMethod(
nameof(this.Bar),
BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly);
}
public static void Bar()
{
}
}
}
Types loaded in a reflection-only context enforce this at runtime, but for all types it's still an optimization and possibly a security improvement.
For troubleshooting #44
namespace RoslynSandbox
{
using System.Reflection;
using NUnit.Framework;
class Foo
{
internal static class Bar
{
}
}
class Tests
{
[Test]
public void SomeTest()
{
Assert.NotNull(typeof(Foo).GetNestedType(nameof(Foo.Bar), BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly));
}
}
}
The msdn docs are not awesome here:
A bitmask comprised of one or more BindingFlags that specify how the search is conducted.
Just a reminder, wrote it to only do the check when GetMethod
is invoked with string name only.
@jnm2 you know this right?
Needs ref
probably a bug
๐ญ This is .NET Core 2.1 only. If the project targets anything else, perhaps suggest creating and invoking a typed delegate in order to avoid wrapping with TargetInvocationException?
Before:
class Foo
{
public Foo()
{
var methodInfo = typeof(Foo).GetMethod(nameof(this.Id))
.Invoke(null, new object[] { 1 });
}
public T Id<T>(T value) => value;
}
After:
class Foo
{
public Foo()
{
var methodInfo = typeof(Foo).GetMethod(nameof(this.Id))
.MakeGenericMethod(typeof(int))
.Invoke(null, new object[] { 1 });
}
public T Id<T>(T value) => value;
}
Example GetMethod("Foo") when there is a property named Foo
Instead of relying on hierarchy flattening of public members and walking the inheritance chain. Also could suggest BindingFlags.DeclaredOnly
for perf if that doesn't make the reflection reasoning too brittle.
class Foo
{
public new string ToString() => string.Empty;
}
When doing GetMethod, check flags etc.
Action
& Action<...>
Func<...>
OCD analyzer for max consistency.
Also instead of Array.Empty<Type>()
.
Refactorings should also use this.
List all members in for example GetMethod()
and generate name, bindingflags, types etc.
Generic interface types may be implemented multiple times.
Refactor to .FirstOrDefault(interfaceType => interfaceType.IsGenericType && interfaceType.GetGenericTypeDefinition() == ...)
Severity Code Description Project File Line Suppression State
Warning AD0001 Analyzer 'ReflectionAnalyzers.GetMethodAnalyzer' threw an exception of type 'System.IO.FileNotFoundException' with message 'Could not load file or assembly 'System.Reflection.TypeExtensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies. The system cannot find the file specified.'. Gu.Xml C:\Git\Gu.Xml\Gu.Xml\CSC 1 Active
Type.GetType and Assembly.GetType, suggest adding null check or adding throwOnError: true
.
typeof(Foo).GetProperty("MISSING").GetMethod.Invoke()
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.