0

I have a List<object> which is a collection of various type of objects.

I am writing a helper method which will return a specific type of object. The helper method will accept type name as string parameter.

Note: I am using 3.5 framework.


PHP redirected page doesn't have a referral url

I have two site sitea.com and siteb.com

I need to redirect pages from sitea.com to siteb.com. The redirect script in sitea.com is

<?php
header("Location: http://siteb.com/somepage");
?>

The redirection is taking without any flaw. The functionality if fulfilled. But I have google analytics tracking on siteb.com which should show that the source is referral from sitea.com

I dug into web developer tools in google chrome and found that siteb.com doesn't send a referral header in the request.

How do i redirect my visitors from sitea.com to siteb.com which sends the referral headers on siteb.com.?

4

6 に答える 6

8

If you need to use a string as parameter you can't rely on OfType<T>() extension method. Fortunately it's easy to emulate:

public IEnumerable<object> OfType(this List<object> list, string typeName)
{
    return list.Where(x => x != null && x.GetType().Name == typeName);
}

As pointed out by @ChrisSinclair in the comment this solution does not manage conversions, casts and inheritance/interfaces. Casts (because of user defined conversion operators) and conversions (because of TypeConverters and the IConvertible interface) are little bit more tricky. For simple (implicit) casts (like with inheritance and interfaces) you can use this:

public IEnumerable<object> OfType(this List<object> list, string typeName)
{
    Type type = Type.GetType(typeName);
    return list.Where(x => x != null && type.IsAssignableFrom(x.GetType()));
}

How to perform conversions (even with CUSTOM CONVERSION OPERATORS) at run-time

I found I needed something like the code I posted in this answer but I had to extend it a little bit, here a better implementation that takes care of custom casts and conversions.

Put everything inside a CastExtensions class (or update code if you don't) then declare this small enum for its options:

[Flags]
public enum CastOptions
{
    None = 0,
    ExcludeNulls = 1,
    UseConversions = 2
}

The problem is that C# in general is a statically typed language, it means that almost everything (about types) must be known at compile time (then to perform a cast you have to know type your want to cast to at compile time). This function handles simple cases (like derivation) and more complex ones (interfaces, custom conversion operators - casts - and conversions - when required).

public static IEnumerable<object> OfType(this List<object> list, 
                                         string typeName, CastOptions options)
{
    Type type = Type.GetType(typeName);

    foreach (var obj in list)
    {
        if (Object.ReferenceEquals(obj, null))
        {
            if (options.HasFlag(CastOptions.ExcludeNulls))
                continue;

            yield return obj;
        }

        var objectType = obj.GetType();

        // Derived type?
        if (type.IsAssignableFrom(objectType))
            yield return obj;

        // Should we try to convert?
        if (!options.HasFlag(CastOptions.UseConversions))
            continue;

        // Castable?
        object convertedValue = null;

        try
        {
            var method = typeof(CastExtensions)
                .GetMethod("Cast", BindingFlags.Static|BindingFlags.NonPublic)
                .MakeGenericMethod(type);

            convertedValue = method.Invoke(null, new object[] { obj });
        }
        catch (InvalidCastException)
        {
            // No implicit/explicit conversion operators
        }

        if (convertedValue != null)
            yield return convertedValue;

        // Convertible?
        if (options.HasFlag(CastOptions.UseConversions))
        {
            try
            {
                IConvertible convertible = obj as IConvertible;
                if (convertible != null)
                    convertible.ToType(type, CultureInfo.CurrentCulture);
            }
            catch (Exception)
            {
                // Exact exception depends on the source object type
            }
        }
    }
}

Note that conversion may be or not equivalent to a cast, actually it depends on the implementation and the exact types involved in the operation (that's why you can enable or disable this feature through options).

This is a small helper function needed for cast at run-time:

private static T Cast<T>(object obj)
{
    return (T)obj;
}

We may emit this code at run-time (I suppose even using expressions but I didn't try) but a small helper method will generate exactly the code we need (conversion from an object to a generic known at run-time type). Note that this cast function doesn't work as expected for value types, for example:

int a = 1;
float a = Cast<float>(a); // Run-time error

This is because (object)1 cannot be converted to anything else than int (this is true for all boxed value types). If you're using C# 4.0 you should change object for parameter obj to dynamic and everything will work as expected (for all types).

于 2012-12-21T15:25:23.260 に答える
2

たぶんそのようなもの:

var ofTypeTypeA = myList.OfType<TypeA>();
于 2012-12-21T15:22:39.167 に答える
0

A clean way is to force the user to specify the type as type to avoid loose strings in your application.

Then you could use generics and just use the type you are interested in. That would also allow the caller to skip the cast when using the IEnumerable later.

So instead of this:

List<object> newList = GetOfType(myList, "SomeObject");
// CAST!!
SomeObject someObject = newList[0] as SomeObject;
if (someObject != null)
    // use object

you would just do:

IEnumerable<SomeObject> newList = myList.OfType<SomeObject>();
foreach (SomeObject someObject in newList){
    // no cast neccessary

This makes it unsensitive in the future if you should rename the class SomeObject (because refactoring tools would pick up on the class name instead of the string)

于 2012-12-21T15:32:40.073 に答える
-1

You can use Enumerable.OfType

var input = new List<object>();
input.Add(1);
input.Add("foo");
var bar = input.OfType<string>();
于 2012-12-21T15:23:57.483 に答える
-1

I guess you need to cast a single object extracted from the list to a strongly-typed object. And not to cast all the list to it. Otherwise use List<MyType>.

So I would go with this: How to cast to a type in C#.

于 2012-12-21T15:32:03.530 に答える
-3

You could use the is operator (or pass the type and check for that also using is). Here is an example of using the is operator:

foreach (var ctl in ControlsList)
{
    if (ctl is CheckBox)
        //Do this
    else if (ctl is TextBox)
        //DoThis
}

And by passing the type as string in the parameter, you could do something similar to get the type to test against:

Type t = System.Type.GetType("System.Int32");
于 2012-12-21T15:25:22.240 に答える