Skip to content
Craig Fowler edited this page Mar 9, 2020 · 2 revisions

The packages in this repository provide a variety of reflection-related functionality.

CSF.Reflector

CSF.Reflector provides static reflection, providing a better way to get implementations of MemberInfo than hard-coding to the names of the members.

CSF.ReflectionSpecifications

The package CSF.ReflectionSpecifications includes a small number of classes implementing ISpecificationExpression used for matching/filtering types. This may be useful for the purpose of assembly-scanning.

CSF.Reflection

The package CSF.Reflection has an assortment of small pieces of logic, too small to warrant their own packages.

Type providers for assembly scanning

Assembly-scanning is the process of finding all of the types within an assembly which meet some kind of criteria. The interface IGetsTypes is intended to act as an abstraction between consuming code and the Assembly type, which is difficult to substitute for unit testing. There are four implementations available:

  • AssemblyAllTypesProvider
  • AssemblyAllTypesAdapter
  • AssemblyExportedTypesProvider
  • AssemblyExportedTypesAdapter
  • AggregatingTypesAdapter

Each of these implementations may be instantiated and then passed as constructor dependencies to types which require assembly-scanning.

The adapter types

The two 'assembly adapter' classes accept a System.Reflection.Assembly as a constructor parameter. They will expose the types within that arbitrary assembly. The 'exported types' implementation will return only the types which would be exposed to consuming assemblies (for example, those which are public). The 'all types' implementation will return all types in the assembly, including internal ones.

The aggregating types adapter accepts a constructor parameter of zero or more other implementations of IGetsTypes. It will return all of the types which are returned by all of those providers.

The provider types

The two 'provider' classes are intended to be subclassed in your own application. There is no need to override any functionality; it is normal to leave the class definition blank.

Instances of these subclasses will provide types from the assembly where the subclass is declared. This removes the need for static usages of Assembly.GetAssembly(Type) or typeof(T).Assembly. These mechanisms can break as types are moved around between assemblies. The subclass of the 'provider' type is intended to be used as an assembly-marker of sorts, always remaining in the same assembly.

Detecting the Mono runtime

The service MonoRuntimeDetector, implementing the interface IDetectsMono uses the recommended mechanism of detecting whether or not the current application is executing using the Mono runtime.

Beware of over-using this feature; it's often not required to directly detect Mono, because there are usually other, better techniques, such as detecting a Unix-like environment. This is particularly important given the advent of dotnet core, which supports Unix-like operating systems directly.

Get default value for a type

A very small extension method for System.Type gets the default value for that type (EG: null for any reference type, or a zero-equivalent for a value type). This is equivalent to default(T) except that it works at runtime, with any type.

The extension method is named GetDefaultValue().

Getting embedded text files verbatim

A common usage of embedded resources is to directly embed a text file into an assembly. A common use-case for this technique is to embed a complex SQL script into the application's assembly, rather than include it as a string constant inside a code file.

In this case, we do not wish to use a ResourceManager or an auto-generated .designer.cs resource class to get the file content. The two extension methods for the Assembly type provide direct access to the resource text. These methods are named GetManifestResourceText(). One overload uses a simple resource name, the other uses the same type-and-name naming scheme available in Assembly.GetManifestResourceStream().