Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can't set up "private protected" properties

Closed
RobSiklos opened this issue Jun 10, 2021 · 5 comments · Fixed by #1257
Closed

Can't set up "private protected" properties #1170

RobSiklos opened this issue Jun 10, 2021 · 5 comments · Fixed by #1257

Comments

@RobSiklos
Copy link
Contributor

RobSiklos commented Jun 10, 2021

I can set up protected properties, I can set up internal properties, and I can set up protected internal properties. However, I cannot set up properties which are the strict intersection of protected and internal (in C# called "private protected"). As a reminder, "protected internal" is the union of protected and internal.

Since protected and internal both work, I see no reason why "private protected" shouldn't work as well.

Test code:

public class C
{
    public string PropValue_Internal => this.Internal;
    public string PropValue_Protected => this.Protected;
    public string PropValue_ProtectedInternal => this.ProtectedInternal;
    public string PropValue_PrivateProtected => this.PrivateProtected;

    internal virtual string Internal => throw new NotImplementedException("Internal not mocked");
    protected virtual string Protected => throw new NotImplementedException("Protected not mocked");
    protected internal virtual string ProtectedInternal => throw new NotImplementedException("ProtectedInternal not mocked");
    private protected virtual string PrivateProtected => throw new NotImplementedException("PrivateProtected not mocked");
}

class Program
{
    static void Main(string[] args)
    {
        var mock = new Mock<C>();

        mock.Protected().SetupGet<string>("Internal").Returns("Internal mocked");
        mock.Protected().SetupGet<string>("Protected").Returns("Protected mocked");
        mock.Protected().SetupGet<string>("ProtectedInternal").Returns("ProtectedInternal mocked");
        mock.Protected().SetupGet<string>("PrivateProtected").Returns("PrivateProtected mocked");

        // These work.
        Console.WriteLine(mock.Object.PropValue_Internal);
        Console.WriteLine(mock.Object.PropValue_Protected);
        Console.WriteLine(mock.Object.PropValue_ProtectedInternal);

        // This will throw a NotImplementedException with the message "PrivateProtected Not mocked".
        Console.WriteLine(mock.Object.PropValue_PrivateProtected);
    }
}
@stakx stakx added the question label Jun 10, 2021
@stakx
Copy link
Member

stakx commented Jun 10, 2021

Like you said, protected internal is the union of the two: protected OR internal. private protected on the other hand is the conjunction: protected AND internal. You only have access to such members from inside their own assembly, and only from their declaring type or a subtype or (IIRC) a nested type.

Outside the assembly where such members are declared, they're essentially the same as private members... and you're probably not surprised why you cannot set up those.

@RobSiklos
Copy link
Contributor Author

RobSiklos commented Jun 10, 2021

@stakx I will have to disagree with you.

If I have a private protected member in assembly A, and assembly B is a friend, then that member is in fact accessible to derived types in assembly B, is it not? This is much different than private.

How is this any different for Moq? If I've got the InternalsVisibleTo("DynamicProxyGenAssembly2...") attribute on the assembly, thereby giving Moq access to the internals in my assembly, that's explicitly saying that I want Moq to be able to access (and thereby potentially override) internal members.

So really, private protected shouldn't be any less visible than internal from the perspective of Moq. The only difference between private protected and internal is that we've got the extra protected restriction. However, Moq already clearly wants to address the protected situation, which is the whole reason for the Moq.Protected namespace.

@stakx
Copy link
Member

stakx commented Jun 10, 2021

Ah yes, I believe you're correct. And, come to think of it, I suspect the reason why this currently doesn't work is a different one: support for intercepting private protected methods was added only recently to DynamicProxy (upon which Moq v4 is built); see castleproject/Core#535. This enhancement will be released in DynamicProxy v5, once we update our dependency in Moq, such methods should be supported, too.

@RobSiklos
Copy link
Contributor Author

RobSiklos commented Jun 10, 2021

Thanks @stakx . Can you provide any idea of when DynamicProxy v5 will be released? Seems like there's hasn't been much activity there since March, and there aren't any open issues in the 5.0.0 milestone.

@stakx
Copy link
Member

stakx commented Jun 10, 2021

I cannot say. You best watch this or their repository's releases; I can assure you there'll be a Moq release very soon after DP v5 is published.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants