문제

I have two file. One of this is a class declaration and other is interface declaration. Class should implements interface. How can I check in NRefactory if class implements interface methods?

I should give more details.

First file - for example:

class Test : IF
{
}

and the second

interface IF
{
    void Foo();
}

I have to read these files and parse with NRefactory. I need to check if class Test implements method from interface IF.

Without compilation and loading compiled assembly.

도움이 되었습니까?

해결책 2

I found solution in NRefactory code. I've modified this in order to achive my goals. First we should implement visitor which check if classes implements each method from interface:

public class MissingInterfaceMemberImplementationVisitor : DepthFirstAstVisitor
{
    private readonly CSharpAstResolver _resolver;
    public bool IsInterfaceMemberMissing { get; private set; }
    public MissingInterfaceMemberImplementationVisitor(CSharpAstResolver resolver)
    {
        _resolver = resolver;
        IsInterfaceMemberMissing = false;
    }

    public override void VisitTypeDeclaration(TypeDeclaration typeDeclaration)
    {
        if (typeDeclaration.ClassType == ClassType.Interface || typeDeclaration.ClassType == ClassType.Enum)
            return;
        base.VisitTypeDeclaration(typeDeclaration);
        var rr = _resolver.Resolve(typeDeclaration);
        if (rr.IsError)
            return;
        foreach (var baseType in typeDeclaration.BaseTypes)
        {
            var bt = _resolver.Resolve(baseType);
            if (bt.IsError || bt.Type.Kind != TypeKind.Interface)
                continue;
            bool interfaceMissing;
            var toImplement = ImplementInterfaceAction.CollectMembersToImplement(rr.Type.GetDefinition(), bt.Type, false, out interfaceMissing);
            if (toImplement.Count == 0)
                continue;

            IsInterfaceMemberMissing = true;
        }
    }
}

And now we have to read all files, parse them and invoke above class in a following way:

var solutionFiles = new List<FileInfo>();
var trees = new Dictionary<FileInfo, SyntaxTree>();
IProjectContent projectContent = new CSharpProjectContent();
foreach (var file in solutionFiles.Where(f => f.Extension == ".cs").Distinct())
{
    var parser = new ICSharpCode.NRefactory.CSharp.CSharpParser();
    SyntaxTree syntaxTree;
    using (var fs = new FileStream(file.FullName, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, FileOptions.SequentialScan))
    {
        syntaxTree = parser.Parse(fs, file.FullName);
    }
    trees.Add(file, syntaxTree);
    var unresolvedFile = syntaxTree.ToTypeSystem();
    projectContent = projectContent.AddOrUpdateFiles(unresolvedFile);
}
var compilation = projectContent.CreateCompilation();

foreach (var sharpFile in trees)
{
    var originalResolver = new CSharpAstResolver(compilation, sharpFile.Value, sharpFile.Value.ToTypeSystem());
    var visitor = new MissingInterfaceMemberImplementationVisitor(originalResolver);
    sharpFile.Value.AcceptVisitor(visitor);
    if (visitor.IsInterfaceMemberMissing)
       return false;
    }
return true;

다른 팁

Use the is keyword

http://msdn.microsoft.com/en-us/library/scekt9xw.aspx

if (myObj is IMyInterface) {
 ....
}

Alternatively, you can also use as keyword.

class MyClass {  }
interface IInterface {  }

MyClass instance = new MyClass();
var inst = instance as IInterface;
if (inst != null)
{
    // your class implements the interface
}

Use this when you need that instance use afterwards without additional reference typing. Using is you still need to do

if (instance is IInterface) 
{
    var inst = (IInterface) instance;
}

or

(instance as IInterface).InstanceProperty

so why don't do it right away.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top