i have a statement
int A = 10,B=6,C=5;
and i want to write a print function such that i pass the int variable to it and
it prints me the variable name and the value.
eg if i call print(A)
it must return "A: 10", and print (B) then it must return "B:6"
in short i want to know how can i access the name of the variable and print it to string in c#. DO i have to use reflection?
After reading the answers
Hi all, thanks for the suggestions provided. I shall try them out, however i wanted to know if it is at all possible in .NET 2.0? Nothing similar to
#define prt(x) std::cout << #x " = '" << x << "'" << std::endl;
macro which is there in C/C++?
The only sensible way to do this would be to use the Expression API; but that changes the code yet further...
static void Main() {
int A = 10, B = 6, C = 5;
Print(() => A);
}
static void Print<T>(Expression<Func<T>> expression) {
Console.WriteLine("{0}={1}",
((MemberExpression)expression.Body).Member.Name,
expression.Compile()());
}
Note: if this is for debugging purposes, be sure to add [Conditional("DEBUG")] to the method, as using a variable in this way changes the nature of the code in subtle ways.
You can use lambda expressions:
static void Main( string[] args ) {
int A = 50, B = 30, C = 17;
Print( () => A );
Print( () => B );
Print( () => C );
}
static void Print<T>( System.Linq.Expressions.Expression<Func<T>> input ) {
System.Linq.Expressions.LambdaExpression lambda = (System.Linq.Expressions.LambdaExpression)input;
System.Linq.Expressions.MemberExpression member = (System.Linq.Expressions.MemberExpression)lambda.Body;
var result = input.Compile()();
Console.WriteLine( "{0}: {1}", member.Member.Name, result );
}
This is not possible without some 'help' from the call site; even reflection does not know about names of local variables.
This is not possible to do with reflection (see Brian and Joel). In general this is not possible simply because you cannot guarantee a named value is being passed to your print function. For instance, I could just as easily do the following
print(42);
print(A + 42);
Neither of these expressions actually has a name. What would you expect to print here?
Another solution (from a closed post):
Inspired by Jon Skeet's post about Null Reference exception handling and suddenly being reminded about projection there is a way to kinda do that.
Here is complete working codez:
public static class ObjectExtensions {
public static string GetVariableName<T>(this T obj) {
System.Reflection.PropertyInfo[] objGetTypeGetProperties = obj.GetType().GetProperties();
if(objGetTypeGetProperties.Length == 1)
return objGetTypeGetProperties[0].Name;
else
throw new ArgumentException("object must contain one property");
}
}
class Program {
static void Main(string[] args) {
string strName = "sdsd";
Console.WriteLine(new {strName}.GetVariableName());
int intName = 2343;
Console.WriteLine(new { intName }.GetVariableName());
}
}
If you need to support more types than int, use the Expression API but avoid generics and handle the different expression gracefully:
private static string ToDebugOutput(params Expression<Func<object>>[] variables)
{
var sb = new StringBuilder();
foreach (var input in variables)
{
string name;
if (input.Body is UnaryExpression unary && unary.Operand is MemberExpression operand)
{
name = operand.Member.Name;
}
else if (input.Body is MemberExpression member)
{
name = member.Member.Name;
}
else
{
throw new NotSupportedException($"typeof lambda: {input.Body.GetType()}");
}
var result = input.Compile()();
sb.Append($"{name}={result}, ");
}
return sb.ToString();
}
Usage:
string s = "123";
double d = 1.23;
int i2 = 123;
var out2 = ToDebugOutput(() => s, () => d, () => i2);
// out2 = "s=123, d=1.23, i2=123, "
Related
I often need to log or write values of expression and also something that gives context to that. So for example:
WriteLine($"_managedHandlePtr:{_managedHandlePtr}");
WriteLine($"metadata.GetNative(_ptr, handle):{metadata.GetNative(_ptr, handle)}");
Is it possible to get the original expression from an interpolated string? Something like the below in concept. It would be nice if I could eliminate the stringly part of this but get the same output:
LogExpression($"{_managedHandlePtr}");
LogExprsssion($"{metadata.GetNative(_ptr, handle)}");
// Writes the non-interpolated string expression, a colon, then the evaluated string
void LogExpression(FormattableString formattableString)
{
Console.WriteLine(${formattableString.GetExpression()}:{formattableString.ToString()});
}
Output:
_managedHandlePtr:213456
metadata.GetNative(_ptr, handle):0xG5DcS4
It would also be fine if it had to include the notation from the original string:
{_managedHandlePtr}:213456
I don't think you can get much more than the types of the arguments of the FormtableString.
static class Program
{
static void Main(string[] args)
{
Number a = new Number(1.0); // 1.0
Percent b = new Percent(2.0); // 2%
double c = a + b;
Console.WriteLine(Format($"{a} + {b} = {c}"));
// Number + Percent = Double : 1 + 2% = 1.02
}
static string Format(this FormattableString expression, CultureInfo info = null)
{
if (info == null)
{
info = CultureInfo.InvariantCulture;
}
object[] names = expression.GetArguments().Select((arg) => arg.GetType().Name).ToArray();
return $"{string.Format(expression.Format, names)} : {expression.ToString(info)}";
}
}
What I am trying to do is to have an array of references to variables. By which I mean the equivalent to a C array of pointers to ints (for example).
Example: (!!not real code!!)
int a = 4;
int b = 5;
int c = 6;
List<ref int> tmp = new List<ref int>();
tmp.Add(ref a);
tmp.Add(ref b);
tmp.Add(ref c);
tmp[0] = 16;
tmp[1] = 3;
tmp[2] = 1000;
Console.Writeline(tmp[0] + " " + a); // 16 16
Console.Writeline(tmp[1] + " " + b); // 3 3
Console.Writeline(tmp[2] + " " + c); // 1000 1000
The specifics of my case: I have a list of strings that will correspond to the keys in a dictionary. What I think I want to have is a list of Tuples where Type1 is a reference to either an int or string, and Type2 is a reference to an Textbox.
I will be iterating through this list, using the string to get the value from the dictionary (and doing stuff with that data) then storing the results of that into Type1. And eventually I will be taking the data from those Type1 variable references and copying their data to the corresponding Type2 Textbox.
That's the gist of what I think I want to do. If someone thinks that my approach is overly complicated, I will say that I need to keep the Textboxes as they are sadly, so I can't just make an array and iterate through it. And it would be perferable to keep the Type1 variables seperate too, though not quite as necessary.
Now, from reading around, I thought Func<> looked like it was the closest thing to being useful for what I want, so I tried to use the following (with Type1, as an object because it needs to handle both ints and strings)
List<Tuple<string, Func<object>, Func<object>>>
but I was unsure how to use that to get references to the variables.
What you're specifically asking for isn't possible; what would be more appropriate (and has the convenience of actually working!) would be to design a class structure around what you're trying to do.
For instance, something like this:
public class MyObject // Name it appropriately
{
public object Value { get; set; }
public string Key { get; set; }
public TextBox TextBox { get; set; }
}
Then, in your code, you can do something akin to this...
Dictionary<string, object> values = ...
List<MyObject> objects = ...
foreach(var item in objects)
{
item.Value = values[item.Key];
// process your data
item.TextBox = item.Value.ToString();
}
Obviously, this is just a rough design and the class here serves as little more than a data transfer container. You could make the class "smarter" by, for example, using the setter for the Value property to set the value of the TextBox automatically. But this should hopefully give you the general idea of how something like this would be done in an OO fashion.
EDIT Here's how your example would look.
MyObject a = new MyObject() { Value = 4 };
MyObject b = new MyObject() { Value = 5 };
MyObject c = new MyObject() { Value = 6 };
List<MyObject> tmp = new List<MyObject>();
tmp.Add(a);
tmp.Add(b);
tmp.Add(c);
tmp[0].Value = 16;
tmp[1].Value = 3;
tmp[2].Value = 1000;
Console.Writeline(tmp[0].Value.ToString() + " " + a.Value.ToString()); // 16 16
Console.Writeline(tmp[1].Value.ToString() + " " + b.Value.ToString()); // 3 3
Console.Writeline(tmp[2].Value.ToString() + " " + c.Value.ToString()); // 1000 1000
You can't store references using C#. You can only use the ref keyword when calling a method.
You can use pointers, but you can only do that with a fixed expression and within an unsafe context.
It is possible to fake this kind of thing using delegates, but I'm not sure if it's what you're looking for. I'm also fairly sure that you really need to redesign your approach, but nevertheless, here's an example of how you can fake it...
Firstly, write a "value wrapper" class like so:
public class ValueWrapper<T>
{
readonly Func<T> get;
readonly Action<T> set;
public ValueWrapper(Func<T> get, Action<T> set)
{
this.get = get;
this.set = set;
}
public T Value
{
get
{
return get();
}
set
{
set(value);
}
}
}
Then you can use that to change values:
void run()
{
int x = 0;
var intWrapper = new ValueWrapper<int>(() => x, value => x = value);
test(intWrapper);
Console.WriteLine(x); // Prints 42, which shows that x was changed.
TextBox textBox = new TextBox {Text = ""};
var stringWrapper = new ValueWrapper<string>(() => textBox.Text, value => textBox.Text = value);
test(stringWrapper);
Console.WriteLine(textBox.Text); // Prints "Changed".
}
static void test(ValueWrapper<int> wrapper)
{
wrapper.Value = 42;
}
static void test(ValueWrapper<string> wrapper)
{
wrapper.Value = "Changed";
}
You can also create a wrapper in one method and pass it to a different method which uses the wrapper to change a property in the original wrapped object, like so:
void run()
{
TextBox textBox = new TextBox {Text = ""};
var wrapper = test1(textBox);
test2(wrapper);
Console.WriteLine(textBox.Text); // Prints "Changed"
}
void test2(ValueWrapper<string> wrapper)
{
wrapper.Value = "Changed";
}
ValueWrapper<string> test1(TextBox textBox)
{
return new ValueWrapper<string>(() => textBox.Text, value => textBox.Text = value);
}
Warning: This does lead to some fairly head-scratching code, for example:
void run()
{
var intWrapper = test();
intWrapper.Value = 42;
Console.WriteLine(intWrapper.Value); // Works, but where is the value? It can't be the x inside test()!
}
ValueWrapper<int> test()
{
int x = 0;
var intWrapper = new ValueWrapper<int>(() => x, value => x = value);
return intWrapper;
}
So we returned a ValueWrapper from test() which is apparently wrapping a local variable from inside test(). And then we can apparently change the value and print it out...
This isn't really what's happening, of course, but it can be quite confusing!
you can use pointers in this case, use unsafe keyword for method and set project unsafe to allow pointers in c#, also you can encapsulate the value in a class and in C# each class is of reference type
i used this and works perfect:
exp.
public int value1 = 3;
public int value2 = 4;
public int value3 = 5;
public void Method1()
{
int[] values = { value1, value2, value3};
for (int i = 0; i < values.Length; i ++)
{
Console.WriteLine(values[i]);
}
}
there some method equal list() of php in C#?
usage list() in PHP:
$array = array('foo','baa');
list($foo, $baa) = $array;
echo $foo; //foo
echo $baa; //baa
equivalent in javascript:
var arr = ['foo','baa'];
var foo;
var baa;
[foo, baa] = arr;
Thanks in advance!
There is no direct language equivalent in C#. While collection initializers can be used to construct the array, there is no way to extract elements directly.
This requires explicitly setting variables, ie:
var theArray = GetArrayFromSomewhere();
var foo = theArray[0];
var bar = theArray[1];
This is more similar to the original intention, though some might not like all the ceremony :
string a = null, b = null, c = null;
new ValList(v => a = v,
v => b = v,
v => c = v).SetFrom(new string[] { "foo", "bar" });
//here a is "foo", b will be "bar", and c is still null
And the simple helper class:
class ValList
{
private Action<string>[] _setters;
public ValList(params Action<string>[] refs)
{
_setters = refs;
}
internal void SetFrom(string[] values)
{
for (int i = 0; i < values.Length && i < _setters.Length; i++)
_setters[i](values[i]);
}
}
One way to do the original php (I know nothing about PHP) task in C# would be
List<string> name_list = new List<string>{"transmogrify","untransmogrify"};
name_list.ForEach(x => Debug.WriteLine(x));
Which leads to the more general observation, that C# allows you to do a lot while leaving the variables in the array or list. LINQ in particular makes doing many things quite simple. So if you are looking for a way to replicate some PHP code in C# I would think in those terms. Just one parting example, if you had an array of ints you wanted to sum you could do this
int[] some_ints = {1, 2, 3, 4};
int sum += some_ints.Sum();
As Reed said ,
There is no direct language equivalent in C#.
But you can create it like below ↓
class Program
{
static void Main(string[] args)
{
string[] tmp = new string[] { "foo", "baa" };
string foo, baa;
tmp.Go(out foo, out baa);
Console.WriteLine(foo);
Console.WriteLine(baa);
Console.ReadKey();
}
}
public static class PHPList
{
public static void Go(this string[] soruce, out string p1, out string p2)
{
p1 = soruce[0] + "";
p2 = soruce[1] + "";
}
}
Just piggy-backing #Yoni's answer into an extension method. This was a cute and silly exercise; however, as has been pointed out in comments and answers, some language features simply do not port from one language to another.
In PHP, list($a, $b) = $c constitutes an assignment, and since no variable declarations are required (the list() is the declaration) it can provide terse and clean assignment syntax.
In C# however, since variable declarations are required prior to usage, you're better off simply assigning the value off the list at that time, as the following example will show.
Speaking of, incoming example:
public static void Into<TSource>(this IEnumerable<TSource> source,
params Action<TSource>[] actions)
{
if (ReferenceEquals(source, null)) {
throw new ArgumentNullException("source");
}
if (ReferenceEquals(actions, null)) {
throw new ArgumentNullException("actions");
}
foreach (var assignment in actions.Zip(source, (action, item) => new {
Action = action,
Item = item,
})) {
assignment.Action.Invoke(assignment.Item);
}
}
So you can simply collection.Into(o => a = o, o => ...); for example:
var numbers = new[] { 1, 2, 3, 4, 5 };
int a = 0, b = 0, c = 0, d = 0;
int e = 0, f = 0, g = 0, h = 0, i = 0, j = 0;
numbers.Into(o => a = o,
o => b = o,
o => c = o,
o => d = o);
numbers.Into(o => e = o,
o => f = o,
o => g = o,
o => h = o,
o => i = o,
o => j = o);
This will yield:
Console.WriteLine(a); // 1
Console.WriteLine(b); // 2
Console.WriteLine(c); // 3
Console.WriteLine(d); // 4
Console.WriteLine(e); // 1
Console.WriteLine(f); // 2
Console.WriteLine(g); // 3
Console.WriteLine(h); // 4
Console.WriteLine(i); // 5
Console.WriteLine(j); // 0
Perhaps some Expression<> magic can shorten it to:
numbers.Into(o => a,
o => b,
... )
Is there a way to get all types used inside C# method?
For example,
public int foo(string str)
{
Bar bar = new Bar();
string x = "test";
TEST t = bar.GetTEST();
}
would return: Bar, string and TEST.
All I can get now is the method body text using EnvDTE.CodeFunction. Maybe there is a better way to achieve it than trying to parse this code.
I'm going to take this opportunity to post up a proof of concept I did because somebody told me it couldn't be done - with a bit of tweaking here and there, it'd be relatively trivial to extend this to extract out all referenced Types in a method - apologies for the size of it and the lack of a preface, but it's somewhat commented:
void Main()
{
Func<int,int> addOne = i => i + 1;
Console.WriteLine(DumpMethod(addOne));
Func<int,string> stuff = i =>
{
var m = 10312;
var j = i + m;
var k = j * j + i;
var foo = "Bar";
var asStr = k.ToString();
return foo + asStr;
};
Console.WriteLine(DumpMethod(stuff));
Console.WriteLine(DumpMethod((Func<string>)Foo.GetFooName));
Console.WriteLine(DumpMethod((Action)Console.Beep));
}
public class Foo
{
public const string FooName = "Foo";
public static string GetFooName() { return typeof(Foo).Name + ":" + FooName; }
}
public static string DumpMethod(Delegate method)
{
// For aggregating our response
StringBuilder sb = new StringBuilder();
// First we need to extract out the raw IL
var mb = method.Method.GetMethodBody();
var il = mb.GetILAsByteArray();
// We'll also need a full set of the IL opcodes so we
// can remap them over our method body
var opCodes = typeof(System.Reflection.Emit.OpCodes)
.GetFields()
.Select(fi => (System.Reflection.Emit.OpCode)fi.GetValue(null));
//opCodes.Dump();
// For each byte in our method body, try to match it to an opcode
var mappedIL = il.Select(op =>
opCodes.FirstOrDefault(opCode => opCode.Value == op));
// OpCode/Operand parsing:
// Some opcodes have no operands, some use ints, etc.
// let's try to cover all cases
var ilWalker = mappedIL.GetEnumerator();
while(ilWalker.MoveNext())
{
var mappedOp = ilWalker.Current;
if(mappedOp.OperandType != OperandType.InlineNone)
{
// For operand inference:
// MOST operands are 32 bit,
// so we'll start there
var byteCount = 4;
long operand = 0;
string token = string.Empty;
// For metadata token resolution
var module = method.Method.Module;
Func<int, string> tokenResolver = tkn => string.Empty;
switch(mappedOp.OperandType)
{
// These are all 32bit metadata tokens
case OperandType.InlineMethod:
tokenResolver = tkn =>
{
var resMethod = module.SafeResolveMethod((int)tkn);
return string.Format("({0}())", resMethod == null ? "unknown" : resMethod.Name);
};
break;
case OperandType.InlineField:
tokenResolver = tkn =>
{
var field = module.SafeResolveField((int)tkn);
return string.Format("({0})", field == null ? "unknown" : field.Name);
};
break;
case OperandType.InlineSig:
tokenResolver = tkn =>
{
var sigBytes = module.SafeResolveSignature((int)tkn);
var catSig = string
.Join(",", sigBytes);
return string.Format("(SIG:{0})", catSig == null ? "unknown" : catSig);
};
break;
case OperandType.InlineString:
tokenResolver = tkn =>
{
var str = module.SafeResolveString((int)tkn);
return string.Format("('{0}')", str == null ? "unknown" : str);
};
break;
case OperandType.InlineType:
tokenResolver = tkn =>
{
var type = module.SafeResolveType((int)tkn);
return string.Format("(typeof({0}))", type == null ? "unknown" : type.Name);
};
break;
// These are plain old 32bit operands
case OperandType.InlineI:
case OperandType.InlineBrTarget:
case OperandType.InlineSwitch:
case OperandType.ShortInlineR:
break;
// These are 64bit operands
case OperandType.InlineI8:
case OperandType.InlineR:
byteCount = 8;
break;
// These are all 8bit values
case OperandType.ShortInlineBrTarget:
case OperandType.ShortInlineI:
case OperandType.ShortInlineVar:
byteCount = 1;
break;
}
// Based on byte count, pull out the full operand
for(int i=0; i < byteCount; i++)
{
ilWalker.MoveNext();
operand |= ((long)ilWalker.Current.Value) << (8 * i);
}
var resolved = tokenResolver((int)operand);
resolved = string.IsNullOrEmpty(resolved) ? operand.ToString() : resolved;
sb.AppendFormat("{0} {1}",
mappedOp.Name,
resolved)
.AppendLine();
}
else
{
sb.AppendLine(mappedOp.Name);
}
}
return sb.ToString();
}
public static class Ext
{
public static FieldInfo SafeResolveField(this Module m, int token)
{
FieldInfo fi;
m.TryResolveField(token, out fi);
return fi;
}
public static bool TryResolveField(this Module m, int token, out FieldInfo fi)
{
var ok = false;
try { fi = m.ResolveField(token); ok = true; }
catch { fi = null; }
return ok;
}
public static MethodBase SafeResolveMethod(this Module m, int token)
{
MethodBase fi;
m.TryResolveMethod(token, out fi);
return fi;
}
public static bool TryResolveMethod(this Module m, int token, out MethodBase fi)
{
var ok = false;
try { fi = m.ResolveMethod(token); ok = true; }
catch { fi = null; }
return ok;
}
public static string SafeResolveString(this Module m, int token)
{
string fi;
m.TryResolveString(token, out fi);
return fi;
}
public static bool TryResolveString(this Module m, int token, out string fi)
{
var ok = false;
try { fi = m.ResolveString(token); ok = true; }
catch { fi = null; }
return ok;
}
public static byte[] SafeResolveSignature(this Module m, int token)
{
byte[] fi;
m.TryResolveSignature(token, out fi);
return fi;
}
public static bool TryResolveSignature(this Module m, int token, out byte[] fi)
{
var ok = false;
try { fi = m.ResolveSignature(token); ok = true; }
catch { fi = null; }
return ok;
}
public static Type SafeResolveType(this Module m, int token)
{
Type fi;
m.TryResolveType(token, out fi);
return fi;
}
public static bool TryResolveType(this Module m, int token, out Type fi)
{
var ok = false;
try { fi = m.ResolveType(token); ok = true; }
catch { fi = null; }
return ok;
}
}
If you can access the IL for this method, you might be able to do something suitable. Perhaps look at the open source project ILSpy and see whether you can leverage any of their work.
As others have mentioned, if you had the DLL you could use something similar to what ILSpy does in its Analyze feature (iterating over all the IL instructions in the assembly to find references to a specific type).
Otherwise, there is no way to do it without parsing the text into a C# Abstract Syntax Tree, AND employing a Resolver - something that can understand the semantics of the code well enough to know if "Bar" in your example is indeed a name of a type that is accessible from that method (in its "using" scope), or perhaps the name of a method, member field, etc... SharpDevelop contains a C# parser (called "NRefactory") and also contains such a Resolver, you can look into pursuing that option by looking at this thread, but beware that it is a fair amount of work to set it up to work right.
I just posted an extensive example of how to use Mono.Cecil to do static code analysis like this.
I also show a CallTreeSearch enumerator class that can statically analyze call trees, looking for certain interesting things and generating results using a custom supplied selector function, so you can plug it with your 'payload' logic, e.g.
static IEnumerable<TypeUsage> SearchMessages(TypeDefinition uiType, bool onlyConstructions)
{
return uiType.SearchCallTree(IsBusinessCall,
(instruction, stack) => DetectTypeUsage(instruction, stack, onlyConstructions));
}
internal class TypeUsage : IEquatable<TypeUsage>
{
public TypeReference Type;
public Stack<MethodReference> Stack;
#region equality
// ... omitted for brevity ...
#endregion
}
private static TypeUsage DetectTypeUsage(
Instruction instruction, IEnumerable<MethodReference> stack, bool onlyConstructions)
{
TypeDefinition resolve = null;
{
TypeReference tr = null;
var methodReference = instruction.Operand as MethodReference;
if (methodReference != null)
tr = methodReference.DeclaringType;
tr = tr ?? instruction.Operand as TypeReference;
if ((tr == null) || !IsInterestingType(tr))
return null;
resolve = tr.GetOriginalType().TryResolve();
}
if (resolve == null)
throw new ApplicationException("Required assembly not loaded.");
if (resolve.IsSerializable)
if (!onlyConstructions || IsConstructorCall(instruction))
return new TypeUsage {Stack = new Stack<MethodReference>(stack.Reverse()), Type = resolve};
return null;
}
This leaves out a few details
implementation of IsBusinessCall, IsConstructorCall and TryResolve as these are trivial and serve as illustrative only
Hope that helps
The closest thing to that that I can think of are expression trees. Take a look at the documentation from Microsoft.
They are very limited however and only work on simple expressions and not full methods with statement bodies.
Edit: Since the intention of the poster was to find class couplings and used types, I would suggest using a commercial tool like NDepend to do the code analysis as an easy solution.
This definitely cannot be done from reflection (GetMethod(), Expression Trees, etc.). As you mentioned, using EnvDTE's CodeModel is an option since you get line-by-line C# there, but using it outside Visual Studio (that is, processing an already existing function, not in your editor window) is nigh-impossible, IMHO.
But I can recommend Mono.Cecil, which can process CIL code line-by-line (inside a method), and you can use it on any method from any assembly you have reference to. Then, you can check every line if it is a variable declaration (like string x = "test", or a methodCall, and you can get the types involved in those lines.
With reflection you can get the method. This returns a MethodInfo object, and with this object you cannot get the types which are used in the method. So I think the answer is that you cannot get this native in C#.
This question has answer in other languages/platforms but I couldn't find a robust solution in C#. Here I'm looking for the part of URL which we use in WHOIS so I'm not interested in sub-domains, port, schema, etc.
Example 1: http://s1.website.co.uk/folder/querystring?key=value => website.co.uk
Example 2: ftp://username:password#website.com => website.com
The result should be the same when the owner in whois is the same so sub1.xyz.com and sub2.xyz.com both belong to who has the xyz.com which I'm need to extract from a URL.
I needed the same, so I wrote a class that you can copy and paste into your solution. It uses a hard coded string array of tld's. http://pastebin.com/raw.php?i=VY3DCNhp
Console.WriteLine(GetDomain.GetDomainFromUrl("http://www.beta.microsoft.com/path/page.htm"));
outputs microsoft.com
and
Console.WriteLine(GetDomain.GetDomainFromUrl("http://www.beta.microsoft.co.uk/path/page.htm"));
outputs microsoft.co.uk
As #Pete noted, this is a little bit complicated, but I'll give it a try.
Note that this application must contain a complete list of known TLD's. These can be retrieved from http://publicsuffix.org/. Left extracting the list from this site as an exercise for the reader.
class Program
{
static void Main(string[] args)
{
var testCases = new[]
{
"www.domain.com.ac",
"www.domain.ac",
"domain.com.ac",
"domain.ac",
"localdomain",
"localdomain.local"
};
foreach (string testCase in testCases)
{
Console.WriteLine("{0} => {1}", testCase, UriHelper.GetDomainFromUri(new Uri("http://" + testCase + "/")));
}
/* Produces the following results:
www.domain.com.ac => domain.com.ac
www.domain.ac => domain.ac
domain.com.ac => domain.com.ac
domain.ac => domain.ac
localdomain => localdomain
localdomain.local => localdomain.local
*/
}
}
public static class UriHelper
{
private static HashSet<string> _tlds;
static UriHelper()
{
_tlds = new HashSet<string>
{
"com.ac",
"edu.ac",
"gov.ac",
"net.ac",
"mil.ac",
"org.ac",
"ac"
// Complete this list from http://publicsuffix.org/.
};
}
public static string GetDomainFromUri(Uri uri)
{
return GetDomainFromHostName(uri.Host);
}
public static string GetDomainFromHostName(string hostName)
{
string[] hostNameParts = hostName.Split('.');
if (hostNameParts.Length == 1)
return hostNameParts[0];
int matchingParts = FindMatchingParts(hostNameParts, 1);
return GetPartOfHostName(hostNameParts, hostNameParts.Length - matchingParts);
}
private static int FindMatchingParts(string[] hostNameParts, int offset)
{
if (offset == hostNameParts.Length)
return hostNameParts.Length;
string domain = GetPartOfHostName(hostNameParts, offset);
if (_tlds.Contains(domain.ToLowerInvariant()))
return (hostNameParts.Length - offset) + 1;
return FindMatchingParts(hostNameParts, offset + 1);
}
private static string GetPartOfHostName(string[] hostNameParts, int offset)
{
var sb = new StringBuilder();
for (int i = offset; i < hostNameParts.Length; i++)
{
if (sb.Length > 0)
sb.Append('.');
sb.Append(hostNameParts[i]);
}
string domain = sb.ToString();
return domain;
}
}
The closest you could get is the System.Uri.Host property, which would extract the sub1.xyz.com portion. Unfortunately, it's hard to know what exactly is the "toplevel" portion of the host (e.g. sub1.foo.co.uk versus sub1.xyz.com)
if you need to domain name then you can use URi.hostadress in .net
if you need the url from content then you need to parse them using regex.