简体   繁体   中英

C# - Type conversion issue when calling base class method from derived class

I need to retrieve an extended attribute from Active Directory, for which there is a private method in the ComputerPrincipal class. I understand I can only access the private method through a derived class, so I've derived a class ComputerPrincipalEx from the base class. I've then created (defined?) a method in the derived class which calls the private method in the base class. This part seems OK.

The problem comes when I try to use a (public) method of the base class to assign a value to a variable with the type of the derived class. Here's the code, then I'll try to explain more:

The derived class:

public class ComputerPrincipalEx : ComputerPrincipal
{
    public ComputerPrincipalEx(PrincipalContext context) : base(context) { }

    public ComputerPrincipalEx(PrincipalContext context, string samAccountName, string password, bool enabled) : base(context, samAccountName, password, enabled) { }

    public string ExtensionGet(string extendedattribute)
    {
        return (string) base.ExtensionGet(extendedattribute)[0];
    }

}

The problem code, which itself is a method of another class I've created:

 public string GetExtendedAttribute(string attributeName) { PrincipalContext ctx = new PrincipalContext(ContextType.Domain); ComputerPrincipalEx cp = new ComputerPrincipalEx(ctx); cp = ComputerPrincipalEx.FindByIdentity(ctx, Name); return cp.ExtensionGet(attributeName); } 

ExtensionGet is the private method of the base class that I need to expose, and I think I have this correct because once I create an object of type ComputerPrincipalEx , I can access ExtensionGet , which is otherwise inaccessible.

The problem is the type conversion in this line: cp = ComputerPrincipalEx.FindByIdentity(ctx, Name);

cp is defined as ComputerPrincipalEx; ComputerPrincipalEx.FindByIdentity references the base ComputerPrincipal.FindByIdentity method, and returns a ComputerPrincipal . The compiler balks about an implicit conversion between types. Casting ComputerPrincipal to ComputerPrincipalEx satisfies the compiler but the app crashes at runtime because it can't perform the conversion.

Now, I pretty much understand all of that, but I'm assuming there has to be some way to call a method from the base class and return valid data to an object of the derived class' type, and that's what I'm hoping to find out how to do.

I was able to figure this out based on information I found here and here .

In the derived ComputerPrincipalEx class, I needed to hide the base class' FindByIdentity method and redefine it to call FindByIdentityWithType . This let me cast the return type to be ComputerPrincipalEx and thus access the ExtensionGet method. (Hopefully I'm explaining that properly; this is still very new to me.)

For this to work however, the below lines needed to be added as well. Otherwise the compiler threw an error that ComputerPrincipalEx was not a valid object type to search with.

[DirectoryObjectClass("computer")]
[DirectoryRdnPrefix("CN")]

Here's the relevant excerpt from the ComputerPrincipalEx class: (Yes, I know the try/catch block needs some work.)

[DirectoryObjectClass("computer")]
[DirectoryRdnPrefix("CN")]

public class ComputerPrincipalEx : ComputerPrincipal
{
    public ComputerPrincipalEx(PrincipalContext context) : base(context) { }

    public ComputerPrincipalEx(PrincipalContext context, string samAccountName, string password, bool enabled) : base(context, samAccountName, password, enabled) { }

    new public string ExtensionGet(string extendedattribute)
    {
        try
        {
            if (base.ExtensionGet(extendedattribute).Length != 1)
            {
                return null;
            }
            else
            {
                return (string)base.ExtensionGet(extendedattribute)[0];
            }
        }
        catch (Exception ex)
        {
            // This should be broken down to individual exceptions
            string message = string.Format("Exception occurred while retrieving extended attribute {0}. \r\nThe following error occurred:\r\n {1}", extendedattribute, ex);
            MessageBox.Show(message);
            Application.Exit();
            return null;
        }
    }

    public static new ComputerPrincipalEx FindByIdentity(PrincipalContext ctx, string identityValue)
    {
        return (ComputerPrincipalEx)FindByIdentityWithType(ctx, typeof(ComputerPrincipalEx), identityValue);
    }
}

And the revised GetExtendedAttribute call:

    public string GetExtendedAttribute(string attributeName)
    {
        PrincipalContext ctx = new PrincipalContext(ContextType.Domain); 
        var cp = ComputerPrincipalEx.FindByIdentity(ctx, Name); 
        return cp.ExtensionGet(attributeName);

    }

Thanks all for the help. Hopefully this helps someone else who runs into the same problem.

Change to this:

public string GetExtendedAttribute(string attributeName)
    {
        PrincipalContext ctx = new PrincipalContext(ContextType.Domain);
        var cp = ComputerPrincipalEx.FindByIdentity(ctx, Name);
        return cp.ExtensionGet(attributeName);
    }

在我的印象中,您需要ComputerPrincipalEx中的一个构造函数(或静态方法),该构造函数是从基类的实例创建的。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM