Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/xamarin/NRefactory.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/README
diff options
context:
space:
mode:
authorDaniel Grunwald <daniel@danielgrunwald.de>2010-10-10 20:15:29 +0400
committerDaniel Grunwald <daniel@danielgrunwald.de>2010-10-10 20:15:29 +0400
commit9efef610b18befcc639b7f1347be1fb668e4b296 (patch)
tree2f492c74e09f3d285baf53ed50ae5f744477142b /README
parentc4f4db723b781474d61dca855032ffbb4aa924cb (diff)
Rename AggregateTypeResolveContext to CompositeTypeResolveContext.
Rename DotNetName to ReflectionName. Added ReflectionName-parser to ReflectionHelper. Move the ReaderWriterLock synchronization from TypeStorage to SimpleProjectContent. Added some documentation to the README.
Diffstat (limited to 'README')
-rw-r--r--README98
1 files changed, 98 insertions, 0 deletions
diff --git a/README b/README
index efd004bb..37c95516 100644
--- a/README
+++ b/README
@@ -26,3 +26,101 @@ Null-Object pattern:
The pattern also extends to the C# resolver, which always produces a ResolveResult, even in error cases.
Use ResolveResult.IsError to detect resolver errors. Also note that many resolver errors still have a meaningful type attached,
this allows code completion to work in the presence of minor semantic errors.
+
+FAQ:
+Q: What is the difference between a type and a type definition?
+
+A: Basically, a type (IType) is any type in the .NET type system:
+ - an array (ArrayType)
+ - a pointer (PointerType)
+ - a managed reference (ByReferenceType)
+ - a parameterized type (ParameterizedType, e.g. List<int>)
+ - a type parameter (ITypeParameter, e.g. T)
+ - or a type definition (ITypeDefiniton)
+
+ Type definitions are only classes, structs, enums and delegates.
+ Every type definition is a type, but not every type is a type definition.
+ NRefactory's ITypeDefinition derives from IType, so you can directly use any type definition as a type.
+ In the other direction, you could try to cast a type to ITypeDefinition, or you can call the GetDefinition()
+ method. The GetDefinition() method will also return the underlying ITypeDefinition if given a parameterized type,
+ so "List<int>".GetDefinition() is "List<T>".
+
+Q: What is the difference betweent type references and types?
+ I've seen lots of duplicated classes (ArrayType vs. ArrayTypeReference, etc.)
+
+ NRefactory has the concept of the "project content": every assembly/project is stored independently from other assemblies/projects.
+ It is possible to load some source code into a project which contains the type reference "int[]" without having to load
+ mscorlib into NRefactory.
+ So inside the entities stored for the project, the array type is only referenced using an ITypeReference.
+ This interface has a single method:
+ interface ITypeReference {
+ IType Resolve(ITypeResolutionContext context);
+ }
+ By calling the Resolve()-method, you will get back the actual ArrayType.
+ At this point, you have to provide the type resolution context:
+
+ Note that every type can also be used as type reference - the IType interface derives from ITypeReference.
+ Every IType simply returns itself when the Resolve()-method is called.
+ Types are often directly used as references when source and target of the reference are within the same assembly.
+
+A: If you've previously used the .NET Reflection API, the concept of type references is new to you.
+
+
+Q: How do I get the IType or ITypeReference for a primitive type such as string or int?
+
+A: Please use:
+ TypeCode.Int32.ToTypeReference().Resolve(context)
+ Skip the Resolve() call if you only need the type reference.
+
+ ReflectionHelper.ToTypeReference is very fast if given a TypeCode (it simply looks up an existing type reference in an array),
+ and your code will benefit from caching of the resolve result (once that gets implemented for these primitive type references).
+
+ Avoid using "context.GetClass(typeof(int))" - this call involves Reflection on the System.Type being passed,
+ cannot benefit from any caching implemented in the future, and most importantly: it may return null.
+ And do you always test your code in a scenario where mscorlib isn't contained in the resolve context?
+ The approach suggested above will return SharedTypes.UnknownType when the type cannot be resolved, so you
+ don't run into the risk of getting NullReferenceExceptions.
+
+Q: Is it thread-safe?
+
+A: This question is a bit difficult to answer.
+ NRefactory was designed to be usable in a multi-threaded IDE.
+ But of course, this does not mean that everything is thread-safe.
+
+ First off, there's no hidden static state, so any two operations working on independent data can be executed concurrently.
+ TODO: what about the C# parser? gmcs is full of static state...
+
+ Some instance methods may use hidden instance state, so it is not safe to e.g use an instance of the CSharp.Resolver.Conversions class
+ concurrently. Instead, you need to create an instance on every thread.
+
+ In the case of project contents, it is desirable to be able to use them, and all the classes in that project content,
+ on multiple threads - for example to provide code completion in an IDE while a background thread parses more files and adds
+ them to the project content.
+
+ For this reason, the entity interfaces (ITypeDefinition, IMember, etc.) are designed to be freezable. Once the Freeze() method is
+ called, an entity instance becomes immutable and thread-safe.
+
+ Whether an ITypeResolveContext is thread-safe depends on the implementation:
+ TypeStorage: thread-safe for concurrent reads, but only if it's not written to (see XML documentation on TypeStorage)
+ CecilProjectContent: immutable and thread-safe
+ SimpleProjectContent: fully thread-safe
+ CompositeTypeResolveContext: depends on the child contexts
+
+ Usually, you'll work with a set of loaded projects (SimpleProjectContents)
+ and loaded external assemblies (CecilProjectContent).
+ A CompositeTypeResolveContext representing such a set is thread-safe.
+
+ Hoever, some algorithms can become confused if two GetClass() calls with same arguments produce different
+ results (e.g. because another thread updated a class definition).
+ Also, there's a performance problem: if you have a composite of 15 SimpleProjectContents and the resolve algorithm
+ requests 100 types, that's 1500 times entering and leaving the read-lock.
+ Moreoever, the ITypeResolveContext methods that return collections need to create a copy of the collection.
+
+ The solution is to make the read lock more coarse-grained:
+ using (var syncContext = compositeTypeResolveContext.Synchronize()) {
+ resolver.ResolveStuff(syncContext);
+ }
+ On the call to Synchronize(), all 15 SimpleProjectContents are locked for reading.
+ The return value "syncContext" can then be used to access the type resolve context without further synchronization overhead.
+ Once the return value is disposed, the read-locks are released.
+