扩展UserPrincipal后UserPrincipalEx实例返回null的问题求助
扩展UserPrincipal类获取实例返回null的解决方法
我尝试扩展UserPrincipal类以便捷读取AD目录属性,但调试时发现获取的UserPrincipalEx实例user返回null,不过实际能找到目标用户的数据。
现有代码
扩展类代码
public class UserPrincipalEx: UserPrincipal { public UserPrincipalEx(PrincipalContext ctx) : base(ctx) { } public new static UserPrincipalEx FindByIdentity(PrincipalContext ctx, string un) { return UserPrincipal.FindByIdentity(ctx, un) as UserPrincipalEx; } //示例属性获取 [DirectoryProperty("MI")] public string MI { get { if (ExtensionGet("Initials").Length < 1) return null; return ExtensionGet("Initials").ToString(); } set { ExtensionSet("Initials", value); } } }
获取用户信息的代码
PrincipalContext ctx = new PrincipalContext(ContextType.Domain, Environment.UserDomainName); UserPrincipalEx user = UserPrincipalEx.FindByIdentity(ctx, un); //后续处理数据的代码
调试与更新记录
- 调试时
user变量为null,但确认存在目标用户数据 - 20230105:在新项目中尝试了marc_s的解决方案,无效
- 20230106:尝试用
Convert转换UserPrincipal类型失败,报错:Object must implement iConvertible. UserPrincipal does not.,代码如下:
UserPrincipal up = UserPrincipal.FindByIdentity(ctx, un); user = (UserPrincipalEx)Convert.ChangeType(up, typeof(UserPrincipalEx));
问题原因与解决方法
核心问题
UserPrincipal.FindByIdentity返回的是基类UserPrincipal实例,无法通过as关键字直接向下转换为子类UserPrincipalEx,这就是user返回null的原因。此外,扩展属性的特性配置也存在不匹配问题。
修正后的代码
1. 正确实现FindByIdentity方法
替换扩展类中的静态方法,使用Principal.FindByIdentity并指定目标子类类型:
public class UserPrincipalEx : UserPrincipal { public UserPrincipalEx(PrincipalContext ctx) : base(ctx) { } // 正确的FindByIdentity实现 public new static UserPrincipalEx FindByIdentity(PrincipalContext ctx, string identityValue) { return Principal.FindByIdentity(ctx, typeof(UserPrincipalEx), identityValue) as UserPrincipalEx; } // 修正属性映射 [DirectoryProperty("Initials")] public string MI { get { var propertyValues = ExtensionGet("Initials"); return propertyValues.Length > 0 ? propertyValues[0].ToString() : null; } set { ExtensionSet("Initials", value); } } }
2. 关键修正点
- 使用
Principal.FindByIdentity传入typeof(UserPrincipalEx),让AD服务返回正确的子类实例,确保as转换成功。 DirectoryProperty特性的参数必须与AD中的实际属性名一致(这里是Initials,而非MI)。ExtensionGet返回的是对象数组,直接调用ToString()会得到数组类型字符串,需取第一个元素。
内容的提问来源于stack exchange,提问作者jasotastic
相关产品推荐
相关产品推荐

