使用反射设置索引属性的值

3
我试图使用反射来复制以下的C#代码:
UserProfileManager userProfileManager = new UserProfileManager(ServerContextGoesHere);
UserProfile userProfile = null;

userProfile = userProfileManager.GetUserProfile(@"somedomain\someuser");

userProfile["PictureUrl"].Value = "This is where I want to update the value using reflection!";

userProfile.Commit();

使用反射,我可以让所有内容都正常工作,除了我正在尝试在UserProfile对象上设置“PictureUrl”索引属性的那一行。当使用反编译器时,该索引属性看起来像这样:

public UserProfileValueCollection this[string strPropName]

下面是使用反射实现与上述代码相同效果的代码,需要注意的是在 PictureUrl 索引属性处需要设置值(请看 TODO 注释):

   Assembly userProfileAssembly;

    var windowsFolderPath = Environment.GetEnvironmentVariable("windir");
    var pathToServerAssembly = string.Format(@"{0}\assembly\GAC_MSIL\Microsoft.Office.Server.UserProfiles\14.0.0.0__71e9bce111e9429c\Microsoft.Office.Server.UserProfiles.dll", windowsFolderPath);

    try
    {
        userProfileAssembly = Assembly.LoadFrom(pathToServerAssembly);
    }
    catch (FileNotFoundException)
    {
        // Assembly wasn't found, so eject.
        return;
    }

    var userProfileManagerClass = userProfileAssembly.GetType("Microsoft.Office.Server.UserProfiles.UserProfileManager");
    if (userProfileManagerClass == null) return;

    var userExistsMethod = userProfileManagerClass.GetMethod("UserExists");
    if (userExistsMethod == null) return;

    var getUserProfileMethod = userProfileManagerClass.GetMethod("GetUserProfile", new[]{typeof(string)});
    if (getUserProfileMethod == null) return;

    var instantiatedUserProfileManagerClass = Activator.CreateInstance(userProfileManagerClass);
    var result = (bool)userExistsMethod.Invoke(instantiatedUserProfileManagerClass, new object[] { SPContext.Current.Web.CurrentUser.LoginName });

    if (!result) return;

    var userProfileClass = userProfileAssembly.GetType("Microsoft.Office.Server.UserProfiles.UserProfile");
    var userProfile = getUserProfileMethod.Invoke(instantiatedUserProfileManagerClass, new object[] { SPContext.Current.Web.CurrentUser.LoginName });

    //userProfile["PictureUrl"].Value = userPictureUrl;
    //TODO: HOW DO I SET THE PICTUREURL PROPERTY USING REFLECTION?

    var commitMethod = userProfileClass.GetMethod("Commit");
    commitMethod.Invoke(userProfile, null);

Thanks in advance,

Ryan

1个回答

5

假设您在 UserProfile 上只有一个索引器:

PropertyInfo indexProperty = typeof(UserProfile)
    .GetProperties()
    .Single(p => p.GetIndexParameters().Length == 1 && p.GetIndexParameters()[0].ParameterType == typeof(string));

您现在可以获取索引器的值并设置其Value属性:

object collection = indexProperty.GetValue(userProfile, new object[] { "PictureUrl" });

PropertyInfo valueProperty = collection.GetType().GetProperty("Value");
valueProperty.SetValue(collection, userPictureUrl, null);

如果您有多个匹配索引属性,则可以使用以下方式查找:
PropertyInfo indexProperty = (from p in t.GetProperties()
                              let indexParams = p.GetIndexParameters()
                              where indexParams.Length == 1 && indexParams[0].ParameterType == typeof(string)
                              select p).Single();

好的,接近了。当我使用顶部代码块时,indexProperty变成了UserProfileValueCollection,这是属性的正确返回类型。但是当我尝试在其上调用SetValue时,我会得到“找不到属性设置方法”的错误。这是真的,因为该属性没有设置方法。 - Ryan
@Ryan - 抱歉,我稍微误读了问题。我已经更新了答案,我认为这应该解决你的问题。 - Lee

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接