2

I'm trying to access an Internal Method in a sealed class but since it is a sealed class, I'm not able to inherit the Internal Method. The backend portion of the solution I'm working on is designed like that.

I found a work around for this which uses an extension of the class

public static class LocalizationsManagerExtension
{
    public static string AddAppUserBasic(this LocalizationsManager objDotnet, AppUser newUser, string pword)
    {
        try
        {
            objDotnet.AddAppUserBasic(newUser, pword);
            return "Success!";
        }
        catch(Exception ex)
        {
            return ex.Message;
        }
        //return IdentityResult.Success;
        //return System.Threading.Tasks.Task.Run();
        //return "Welcome to the World of DotNet....Mr. " + password;
    }
}

 public ActionResult UserAddNew(UserAddNewModel model)
    {
        if (ModelState.IsValid)
        {

            var user = new DataAccess.AppUser();
            user.Name = model.username;
            user.Password = model.password;
            user.DeveloperRole = model.isDeveloperRole;
            user.AdministratorRole = model.isAdministratorRole;
            user.TranslatorRole = model.isTranslatorRole;
            user.IsDomainUser = model.IsDomainUser;
            user.ManagerRole = model.isManagerRole;
            user.State = Data.Framework.Repository.Helpers.ObjectState.Added;

            var result = LM.AddAppUserBasic(user, user.Password);
            if (result == "Success!")
            {
                ViewBag.ReturnUrl = "/Usermanagement/UserLogin";
                //return RedirectToAction("UserLogin", "UserManagement");
            }
            else {  }
        }


        // If we got this far, something failed, redisplay form
        return View(model);
    }

I tried this but no luck. I'm able to call "AddAppUserBasic" in another method that I'm calling but it is calling the local method. Not the one in the sealed class.

Arden
  • 51
  • 2
  • 5
  • Have a look at the Access-Modifier `internal`, maybe you're missing something about that modifier. [Here](https://msdn.microsoft.com/en-us/library/7c5ka91b.aspx) – Christoph K May 05 '17 at 10:42
  • 1
    ask designers why they decided to make that internal. you should sync your self with rest of team – M.kazem Akhgary May 05 '17 at 10:42
  • You can not inherit anything from sealed class leave alone internal method. – Chetan May 05 '17 at 10:44
  • You are not specifying why you cannot call the internal method. `sealed` and `internal` are not immediately related. Your class is sealed, but it does mean you can create an instance of it. Your method is internal, so you should be able to call it from the assembly where it is defined. Is that assembly under your control? You do not say if so. – Maarten May 05 '17 at 11:57
  • Also, your extension method is just calling itself. – Maarten May 05 '17 at 11:58
  • @Maarten Uhhmmm I can't call the internal method from the front end BECAUSE it is "internal"??? It is only available inside the sealed class? and I'm trying to access it from outside the class? You didn't get that sir? – Arden May 08 '17 at 00:31
  • @arden you didnt mention front-end until now, so no, I didnt 'get that'. You should try to make your question as clear as possible. – Maarten May 08 '17 at 04:54

2 Answers2

7

You MUST NOT access internal methods in classes. Internal methods are internal for a reason. If you think that you should use internal method - first talk to the other programmer why he/she made this method internal. Maybe by mistake. If not, aks if there is other public method that you should use instead.

If you really really really want for some reason to use that method, AND YOU KNOW WHAT YOU'RE DOING

You can use reflection to do that:

using System.Reflection;

Type t = typeof(YourSealedClass); //get the type of your class
YourSealedClass obj = new YourSealedClass(); //somehow get the instance of the class

//find all non public methods
MethodInfo[] methods = t.GetMethods(BindingFlags.NonPublic|BindingFlags.Instance);

//next find your method. You can use LINQ or good old loop:
foreach(MethodInfo mi in methods)
  if(mi.Name == "MethodYouWantToUse")
  {
    mi.Invoke(obj, null);
    break; //leave the loop
  }

You can read more about Invoke here: https://msdn.microsoft.com/pl-pl/library/a89hcwhh(v=vs.110).aspx

Simply - if you call Invoke you have to pass object of the class and parameters of the method - if any.

But remember - doing that you're probably going to mess things up.

Adam Jachocki
  • 1,897
  • 1
  • 12
  • 28
  • Can you explain more why `"you must not access internal methods in classes"`? Surely if the intention is to discourage usage (outside of the class) then you would use private, instead of internal? – musefan May 05 '17 at 12:11
  • You're right. After some deeper reading I have to modify my post a little. – Adam Jachocki May 05 '17 at 12:33
  • 2
    Invoking internal methods is perfectly legitimate. Yes, if you don't know what you're doing, then it's to be discouraged. But if - for instance - you have the source code, and you're on a version-locked library, and need those methods ... then there's literally no reason to avoid it. I wish people would stop hating on it. Internal keeps being wrongly used and abused by developers, so there's plenty of code out there that needn't have been internal and should't be. Reflection is often the only way to fix the code. – Adam Mar 30 '20 at 23:41
  • But you have to aware that this is not the reason of reflection. Reflection has been created rather for other issues. But yes, sometimes this is the only way. – Adam Jachocki Mar 31 '20 at 14:38
  • Worked like a charm to be able to "set" a read-only accessor in a sealed class. – jrsmolley Mar 10 '21 at 04:19
0

Contrary to popular belief, there is a way to access internal methods on a class. The problem is that you really should not do this.

This may not work under certain conditions, but the concept can be proven using this example. Let's start with a sealed class that has an internal method:

namespace ClassLibrary1
{
    public sealed class SealedInternalExample
    {

        internal void TryAndExecuteMe (int someNumber)
        {
            System.Console.WriteLine("Internal method executed.  Parameter: {0}", 
                someNumber);
        }
    }
}

You can't execute SealedInternalExample.TryAndExecuteMe via normal calling conventions. But you can do so via reflection:

namespace CallInternalExample
{
    class Program
    {
        static void Main(string[] args)
        {
            var classInstance = new SealedInternalExample();
            var methods = classInstance.GetType().GetMethods(
                System.Reflection.BindingFlags.NonPublic | 
                System.Reflection.BindingFlags.Public | 
                System.Reflection.BindingFlags.Instance);

            for (int x = 0; x < methods.Length; x++)
                System.Console.WriteLine("{0}: {1}", x, methods[x].Name);

            var internalMethod = methods.FirstOrDefault
                ((m) => m.Name.Equals("TryAndExecuteMe", 
                StringComparison.InvariantCulture));

            internalMethod.Invoke(classInstance, new object[] { 15 });

        }
    }
}

The output of the program is:

0: TryAndExecuteMe
1: ToString
2: Equals
3: GetHashCode
4: GetType
5: Finalize
6: MemberwiseClone
Internal method executed.  Parameter: 15